mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-04 11:00:07 +01:00
1144 lines
42 KiB
Python
1144 lines
42 KiB
Python
#!/usr/bin/env python
|
|
|
|
import sys
|
|
import os
|
|
import wx
|
|
import random
|
|
import datetime
|
|
import math
|
|
import operator
|
|
|
|
import wx.lib.mixins.listctrl as listmix
|
|
import wx.lib.colourdb as cdb
|
|
import wx.lib.colourselect as csel
|
|
import wx.lib.colourutils as cutils
|
|
|
|
from wx.lib.embeddedimage import PyEmbeddedImage
|
|
|
|
import images
|
|
|
|
try:
|
|
dirName = os.path.dirname(os.path.abspath(__file__))
|
|
except:
|
|
dirName = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
|
|
sys.path.append(os.path.split(dirName)[0])
|
|
|
|
try:
|
|
from agw import ultimatelistctrl as ULC
|
|
except ImportError: # if it's not there locally, try the wxPython lib.
|
|
from wx.lib.agw import ultimatelistctrl as ULC
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
musicdata = {
|
|
1 : ("Bad English", "The Price Of Love", "Rock", ""),
|
|
2 : ("DNA featuring Suzanne Vega", "Tom's Diner", "Rock", ""),
|
|
3 : ("George Michael", "Praying For Time", "Rock - HYPERTEXT", ""),
|
|
4 : ("Gloria Estefan", "Here We Are", "Rock", ""),
|
|
5 : ("Linda Ronstadt", "Don't Know Much", "Rock", ""),
|
|
6 : ("Michael Bolton", "How Am I Supposed To Live Without You", "Blues - HYPERTEXT", ""),
|
|
7 : ("Paul Young", "Oh Girl", "Rock", ""),
|
|
8 : ("Paula Abdul", "Opposites Attract", "Rock", ""),
|
|
9 : ("Richard Marx", "Should've Known Better", "Rock", ""),
|
|
10: ("Rod Stewart", "Forever Young (DISABLED)", "Rock", ""),
|
|
11: ("I am a really long item and I am going into overflow", "", "", ""),
|
|
12: ("Sheena Easton", "The Lover In Me", "Rock", ""),
|
|
13: ("Sinead O'Connor", "Nothing Compares 2 U", "Rock", ""),
|
|
14: ("Stevie B.", "Because I Love You", "Rock", ""),
|
|
15: ("Taylor Dayne", "Love Will Lead You Back", "Rock", ""),
|
|
16: ("The Bangles", "Eternal Flame", "Rock", ""),
|
|
17: ("Wilson Phillips", "Release Me", "Rock", ""),
|
|
18: ("Billy Joel", "Blonde Over Blue", "Rock", ""),
|
|
19: ("Billy Joel", "Famous Last Words", "Rock", ""),
|
|
20: ("Billy Joel", "Lullabye (Goodnight, My Angel)", "Rock", ""),
|
|
21: ("Billy Joel", "The River Of Dreams", "Rock", ""),
|
|
22: ("Billy Joel", "Two Thousand Years", "Rock", ""),
|
|
23: ("Janet Jackson", "Alright", "Rock", ""),
|
|
24: ("Janet Jackson", "Black Cat", "Rock", ""),
|
|
25: ("Janet Jackson", "Come Back To Me", "Rock", ""),
|
|
26: ("Janet Jackson", "Escapade", "Rock", ""),
|
|
27: ("Janet Jackson", "Love Will Never Do (Without You)", "Rock", ""),
|
|
28: ("Janet Jackson", "Miss You Much", "Rock", ""),
|
|
29: ("Janet Jackson", "Rhythm Nation", "Rock", ""),
|
|
30: ("Janet Jackson", "State Of The World", "Rock", ""),
|
|
31: ("Janet Jackson", "The Knowledge", "Rock", ""),
|
|
32: ("Spyro Gyra", "End of Romanticism", "Jazz", ""),
|
|
33: ("Spyro Gyra", "Heliopolis", "Jazz", ""),
|
|
34: ("Spyro Gyra", "Jubilee", "Jazz", ""),
|
|
35: ("Spyro Gyra", "Little Linda", "Jazz", ""),
|
|
36: ("Spyro Gyra", "Morning Dance", "Jazz", ""),
|
|
37: ("Spyro Gyra", "Song for Lorraine", "Jazz", ""),
|
|
38: ("Yes", "Owner Of A Lonely Heart", "Rock", ""),
|
|
39: ("Yes", "Rhythm Of Love", "Rock", ""),
|
|
40: ("Cusco", "Dream Catcher", "New Age", ""),
|
|
41: ("Cusco", "Geronimos Laughter", "New Age", ""),
|
|
42: ("Cusco", "Ghost Dance", "New Age", ""),
|
|
43: ("Blue Man Group", "Drumbone", "New Age", ""),
|
|
44: ("Blue Man Group", "Endless Column", "New Age", ""),
|
|
45: ("Blue Man Group", "Klein Mandelbrot", "New Age", ""),
|
|
46: ("Kenny G", "Silhouette", "Jazz", ""),
|
|
47: ("Sade", "Smooth Operator", "Jazz", ""),
|
|
48: ("David Arkenstone", "Papillon (On The Wings Of The Butterfly)", "New Age", ""),
|
|
49: ("David Arkenstone", "Stepping Stars", "New Age", ""),
|
|
50: ("David Arkenstone", "Carnation Lily Lily Rose", "New Age", ""),
|
|
51: ("David Lanz", "Behind The Waterfall", "New Age", ""),
|
|
52: ("David Lanz", "Cristofori's Dream", "New Age", ""),
|
|
53: ("David Lanz", "Heartsounds", "New Age", ""),
|
|
54: ("David Lanz", "Leaves on the Seine", "New Age", ""),
|
|
}
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
_ulcStyles = ["ULC_VRULES", "ULC_HRULES", "ULC_ICON", "ULC_SMALL_ICON", "ULC_LIST",
|
|
"ULC_REPORT", "ULC_TILE", "ULC_ALIGN_TOP", "ULC_ALIGN_LEFT", "ULC_AUTOARRANGE",
|
|
"ULC_VIRTUAL", "ULC_EDIT_LABELS", "ULC_NO_HEADER", "ULC_NO_SORT_HEADER",
|
|
"ULC_SINGLE_SEL", "ULC_SORT_ASCENDING", "ULC_SORT_DESCENDING",
|
|
"ULC_NO_HIGHLIGHT", "ULC_STICKY_HIGHLIGHT", "ULC_STICKY_NOSELEVENT",
|
|
"ULC_SEND_LEFTCLICK", "ULC_HAS_VARIABLE_ROW_HEIGHT", "ULC_AUTO_CHECK_CHILD",
|
|
"ULC_AUTO_TOGGLE_CHILD", "ULC_AUTO_CHECK_PARENT", "ULC_SHOW_TOOLTIPS",
|
|
"ULC_HOT_TRACKING", "ULC_BORDER_SELECT", "ULC_TRACK_SELECT", "ULC_HEADER_IN_ALL_VIEWS",
|
|
"ULC_NO_FULL_ROW_SELECT", "ULC_FOOTER"]
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
coloursBitmap = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0"
|
|
b"RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAnTSURBVHjaYvz//z/DQAKAAGIB"
|
|
b"EXl5DWAO0DGMnJxCScKiKg4cHPzyLMycwoyMTEDx3+///P329P+/z3dPndx25tbd61dd3MLf"
|
|
b"/P707O3GjfMZzGwiGG7dOM5w9uwxkh0AEEBgB+zfvwXM+fPnN4OCgjZHWERkDBurGMO3z0Cx"
|
|
b"30CH/WNgYGVkYGACqnZxcmWwd/j8/O7rN6/vfHj7TFBP+BYX//9TjP//7GBhZHj7h8QABQgg"
|
|
b"RlAUMDIywgU4OTmYSku23BYXdVb69AHiABD+9xdkMiMDMEAY2NkZGLi4GBi+ANl3vjAwnHvy"
|
|
b"g+HblzvPFBkOrL1+uK332YvnD4mNWYAAAjvA3MIR6M0/oChgkJJStLKz7tv366co+6dPDAzf"
|
|
b"vv9n+P7jH8PvP3/BaliZ/wId8J+BnYOVgZeHnUGAn4nhGzBkTjxnYDj4mIFBifHY1YfbA+Pe"
|
|
b"vnt1jhgHAAQQ2AFRMVkMjP9+MPz995tdRiZ0C5+An8uHt98Z2H4+YuBjuMcgznKXQYb9PoMg"
|
|
b"6wcGLqafDOzM/xhYmZgZ/jFxM/xl4Gb4xyLA8IdDluHKZxWGw++ZGNg4T97evn1u4evbb3e8"
|
|
b"/friLz4HAAQQOA38BQbvn//cDDx8mjWCfLYukt/XM/iIrGGQ5jnHIMTxioGV9Tsw9IEJ4T8z"
|
|
b"UDErELNAaSD/NxS/YGLQ/svE4GMjzLCQI05V3sZ5rcb5F9uuzLnadOfB1Qu4HAAQQGAH/AYa"
|
|
b"zMslUxAky1VjzRbDICJ4ioGBGxi5rL8YGIC+BSY/cPwz/Ad65t8fsAP+/wYmjN9A7b9ZGf5/"
|
|
b"ZmT4z8nPwGwpz8CtxsTgwvCA4e6zBvabjhWBEupCLkorg9uObNjZ/+3Pl5/oDgAIIJDJDCpc"
|
|
b"LFX1snd7/ZmnMogw3wLaB0xh/7iBFgJT23+QG/8z/Gf8C0wjwHTyF4h/Ax326yfD/6/fGf69"
|
|
b"BaZUXm4GZmcjBgZ1DSBbjUFK4AMDKzDNuDBOZBAQNeR9k3673TbWo5+TkZsf3QEAAQR2wNsX"
|
|
b"d0T+f3n8D+gNYJIHqvnNAcTsEAzy7T+gsl8gDAwFkB+AifL/V6BDPvxiYBSXY2BydWJgUFNl"
|
|
b"YBASAzpABBiVzAxSPGcYnv3kYPDj6mUQYrRgeB1zM9My3LWLlYmNB9kBAAEEdsC87VtrHFbd"
|
|
b"Klj3gO81w18+oEXcEAx0wH+QI36CMDDOfwAd84OZ4f83YOH06T8Dk5w8A5OzKQODgiwDA58g"
|
|
b"MNqAelmBjge6UlfgDMPLn/+ALBYGP+4eBuY/8gzfk16kaRoaZgAVMMMcABBATFD625Mn96ZG"
|
|
b"rTwR2XeJ/fK/30JAy0COADr2BzA6fgAN/c7B8P87GzDzAx3xgZmBSUaGgdFOmoFBCugwXiDm"
|
|
b"AKpjAqaRv2+BDn/OIMlxCRhlXxg+AZMKDxsvgwd7H8N7lu8MoimCJSK8kg4wBwAEEBNycPz8"
|
|
b"/HZv+ebj0W3n2c7AHQHC37iAvgaGwhdgiLxjZWCSlGBgtAJGlTAwd3B8BfoHiP8D08LvJ0B8"
|
|
b"FxiNLxkE2Z4z8LB8ZQCVX7+B6ViCS5XB6HcNw1uNR+IyVgpxQOvA6QEggJjQE8Wf7x8vN+44"
|
|
b"ET/pGtd5hj+CEAd8B6aNb8AQeM/OwCgmyMBoCfSxAMhioAP+vwHacB8YWteAGJiAfwNLo38/"
|
|
b"GXhZvjHwsH5h+ActEUEOUeUIYWD+q80g7MzlwcbEoQ0SBwggJmx588/X99dqth5P2/GY/zXj"
|
|
b"Hx4GRmA0/P/EycDIx83AZAEMZp73QFVAB/z9AVT8EWjpQ6Dld4D8p6AUCjaWE+g4DuZvDGD7"
|
|
b"oSU9C9A2yd8pDD80f4vJKSkCi18GDoAAYsJVQHz99PZM+YGHJQ++CgHLYS4GRjYOBiZzoKU8"
|
|
b"wDj+9w1UcwFpYNj+BWbJf8Ba6/9nkNMRRSww27Iw/EbiQ7DgfyeGX+xKDHzyXIZAYSGAAGLC"
|
|
b"V0xeun1j5bTrv9czsPAyMBkBfcr7CuhBoIW/gSb9YYGUhP+g4Qv2JtSrMG8D0d9/IHdC4oEJ"
|
|
b"yGdjBibiPxYMjMJ/xYFCAgABhNcBDH9//lx89l7bCV7Gz9+FgcH+A2TxX0iZ8BOIfwAN/vkX"
|
|
b"IvYXpYYBWszK8PsvG9gBv4EO+AtkgOodNrAR1gx/uThA5QEXQACxEKqtXjy/dS5k5s9kmRV8"
|
|
b"/mYqglpuRowqdlovefmkgFUlsFRk+AXMftzAHMIJ8jEzpNQGBsv3v9wMX35ygbnfgdkTFAbf"
|
|
b"/4BijoWB5b8aw08WCWBKZmADCCAWYqrMp48ergEmrwMnLzMJHrlm2mQpLxsqLP3yVab7OwlJ"
|
|
b"ZWDIMPICLWaCRjSQBlbZH37zM7z6xscgwPyH4dO/3+CY+gYMpW+gEPvPysD4SxQcVgABxEJk"
|
|
b"w+W/iIjEawV5FW4zYV6nA7cfHL22686q5fvlpYoChKJivd/K8ygA/cgkAHXIP4aXX8UZXn3m"
|
|
b"ZmBk/cHwD+gIUBh8/8vI8BGYLn8BKz/Gz6yg7PIXIIDADnB2C8PfaABiHj4BBlnWr3Vvntxl"
|
|
b"u/3s4X6g3m13Htx7nDWJd9PWM7L5PdlfIzQsgQkV2DZg4PjLcPWNFsPLj8wMrGwfGT4B23S/"
|
|
b"gEHwE5gWvv1jZPgGDCXObz9/gSpigAACO0BUVAq/94Exyfrviz3nj3vxR+89W/v757dDQOGH"
|
|
b"IB8As+CJrUeuX73+SOnknArOBkf/T/z/fvIwrLjlxPDy0x+G7/9/A+sTYAj8+wtsczACSwkW"
|
|
b"hn/AAkrq2ztQCPwGCCBog+Qv/swATCzyDA/q7r35+vTRs6cgyy8woKT7/5/vPbo7MaZJ/uV6"
|
|
b"Ho7ZotbK3MfuSDJwP9nxh+Hl+Q/sX55++P/nx1d2Ll7mPwKqwj8kTSX/fnoNbHAw/AIIIEga"
|
|
b"ADV7cYB/wIpLkOFVMPff1077rj6bBWwQnALV4NgC6tmLh8vze5V4NI+yFLLtDn/76enZM89+"
|
|
b"/rkEykxA/BFkHDA6uRUVlM2evX/3CSQGEEDgNmFoeCaOsP8P1MHEa8Z28eLhm+8+bj19YwJQ"
|
|
b"dB0Qf8adYFjYgK0XA0hjAhxNrxggrQjkdjKwWgU2JoHVG0AAgUOAlRl7efT52w8mBab7bb9+"
|
|
b"vhLfd+31KqDQSbyWgx39B5S4ThHIVb+gmAEggPCWhCzMDEF/2Hmytz/kuvH968fTQKF71O6a"
|
|
b"AQQQVgeAypN///7x/vrxrusjs8j/q/efngcKX4e5mpoAIIDAUcDGxobmACaGr18/xktLSyke"
|
|
b"OXL4wqePb4H5HtjUpQEACCCwA+7cuYbmAEaGnz+/Xfz+/cv6u3dvXwQKHQGVpLRwAEAAMRDo"
|
|
b"nssAsTLMobQAAAEGABjdycfQA1R2AAAAAElFTkSuQmCC")
|
|
|
|
#----------------------------------------------------------------------
|
|
decryptedBitmap = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0"
|
|
b"RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAUnSURBVHjaYvz//z8DCISGpjLA"
|
|
b"AEjs9+8/DL9+fefh4uKoVlCQi5KQkBBnYmJifPHi2Ztbt66v+/DhfTMrK/Or////AHUwwvXu"
|
|
b"3bsXTAMEEAsDDvD79y95WVnpXV5eHmqSknJA/j8GVlYWBh4eLqlXr57mrFq1NPDKlQs+bGws"
|
|
b"F7DpBwggFuyG/mEBGrrJ399f7f9/NoYdO3b/f/Tozot///7+VVJSl/Lw8GDKzMyXnj69f8Pl"
|
|
b"yxcM2NnZP6CbARBATDDG338MDP/+/WP48+cPAwcHW7OFhaXez59MQEM3/zp58kDO06cPpB4/"
|
|
b"vi+7d+/m8IUL537984eJwc8vTJ6fX7Dj798/DIyMjGAMAwABBDeYjfk/w38WLgYmZlYWdjY2"
|
|
b"75s3b//fu3fb7ydPH7X8Z+Gc9p+ZneEfCycDEyvbmuvXzubt37/7v6KiGoOGhk4o0DF8//4B"
|
|
b"4+Tvf7jBAAEEN9jo9yEGiX+PGThYmf99+cMWfPX2A/X7z16rMjP8a5X5/5RBiuEFgzzjcwY+"
|
|
b"pp8Mv/4xLLpy5fyDHz9+MqioaAoyMzPb/wDGoQjzF7jBAAEED2Puv+8YdH/sZnjDJv/vOyPP"
|
|
b"bYZ/fxmAocPA+f8rg/i/J0A2MwMz0z+Gd0y8DIf+qP159+XrjU+fPikKCokw/mXiUJP6/5rB"
|
|
b"juMJ3GCAAIIb/O8/I8P3XywMvL8eMPCBjISG139gUvrCwAJmgZIVJ+NHBss/ZxjOf+X/+Pnb"
|
|
b"X4Zvf1gZRP5/+GvDcoPh/z9OuMEAAQQ3mJ2TvVtaUTSQiQmUjBn/w0MKbgETPL0y/f/9W4Hl"
|
|
b"gxzrw6UMYj++MYQZM1bz/FfOevH0436gdDpIDUAAMcIyyP4265/2Ee5sIC////sTaNJvIP4F"
|
|
b"9Aowxpn+M7Cw/QHz//z6xfD/538G5r/AZPnjK1COkYGZDehSdm6GU3vu/LHM38sKMg8ggOAu"
|
|
b"5mAH5iseQQYmFiGgjrfA9PcJkgYZgIb/fMLw7No1hn+/fzDIKPMBxXgZGL6yMbADLWQAWsAA"
|
|
b"DBIGRgEGDk5meHoDCCC4wf+BkcXw4zUDAzPQtb/fAzUAY5jpB9DQZwxb5h9gKJrzheEn0BOt"
|
|
b"MSwMMVEyDAx/eKAWgzQD9TL9Yfj/hwue3gACCJHz/gMV/fkIpIFe/guk/wENZv7B8Pv5I4ZF"
|
|
b"W78wPHoH5AKVLdr5h8HP6h0DnxTIAVBzQHpAIfefA24cQAAhGfwfajDQ638+QVz8/zsDK9cf"
|
|
b"BjclJoY7V4G5EqjMXR4YEGzfgb77BTYMkqR+g3IYkBaDGwcQQEwIg0EKvgIxyLWfIfgn0AIB"
|
|
b"RgZ3O04GVXYGBnmgag9TYNYVAFrxB+hiBhgGBTTI2n9w4wACCGEwKFkxgmL+KwQzfAOGGxB/"
|
|
b"+8Jw6/hPhn9A/cxAfbfPgPSzMTDwAb3NxQ7B3ECPc7KiFEIAAYSIPJDBTCCDf0AMBWEWoJdv"
|
|
b"f2QQeP+HIUQD4gzRX/8Z/r1gZGDSARr8AxZXQH0cQMuYEO4ECCAWFBczgILhE9RbQEN/AZ0p"
|
|
b"wsJgVCXEYMwGzSjAoGVkBRrAAsTcMM3MoPQKch3cOIAAQoo8oEImoKH/XgHVsYJdB9Ygzs3A"
|
|
b"iEiekLwHCkqkkgwchKzsyBUJA0AAwQ1mBBnEDTQQWLADy0cGkgDItywsKA4ACCAWpNTGyMAt"
|
|
b"AlQESjbMJBoMTBXMfMCE9QceyAABBDf43vXnp5nnMpswAQv0///+/yfNwSCH/GK6e+X5dWOo"
|
|
b"GECAAQCxvOh5cbsDqwAAAABJRU5ErkJggg==")
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
PIPE_HEIGHT = 18
|
|
PIPE_WIDTH = 300
|
|
|
|
class UltimateRenderer_1(object):
|
|
|
|
DONE_BITMAP = None
|
|
REMAINING_BITMAP = None
|
|
|
|
def __init__(self, parent):
|
|
|
|
self.progressValue = random.randint(1, 99)
|
|
|
|
|
|
def DrawSubItem(self, dc, rect, line, highlighted, enabled):
|
|
"""Draw a custom progress bar using double buffering to prevent flicker"""
|
|
|
|
canvas = wx.Bitmap(rect.width, rect.height)
|
|
mdc = wx.MemoryDC()
|
|
mdc.SelectObject(canvas)
|
|
|
|
if highlighted:
|
|
mdc.SetBackground(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)))
|
|
else:
|
|
mdc.SetBackground(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)))
|
|
mdc.Clear()
|
|
|
|
self.DrawProgressBar(mdc, 0, 0, rect.width, rect.height, self.progressValue)
|
|
|
|
mdc.SetFont(wx.Font(8, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
|
|
text = "%d Mb"%self.progressValue
|
|
textWidth, dummy = mdc.GetTextExtent(text)
|
|
mdc.DrawText(text, rect.width/2 - textWidth/2, rect.height/2 - dummy/2)
|
|
dc.SetClippingRegion(rect.x, rect.y, rect.width, rect.height)
|
|
dc.Blit(rect.x+3, rect.y, rect.width-6, rect.height, mdc, 0, 0)
|
|
dc.DestroyClippingRegion()
|
|
|
|
|
|
def GetLineHeight(self):
|
|
|
|
return PIPE_HEIGHT + 6
|
|
|
|
|
|
def GetSubItemWidth(self):
|
|
|
|
return 130
|
|
|
|
|
|
def UpdateValue(self):
|
|
|
|
self.progressValue += 5
|
|
if self.progressValue >= 100:
|
|
self.progressValue = 1
|
|
|
|
|
|
def DrawHorizontalPipe(self, dc, x, y, w, colour):
|
|
"""Draws a horizontal 3D-looking pipe."""
|
|
|
|
for r in range(PIPE_HEIGHT):
|
|
red = int(colour.Red() * math.sin((math.pi/PIPE_HEIGHT)*r))
|
|
green = int(colour.Green() * math.sin((math.pi/PIPE_HEIGHT)*r))
|
|
blue = int(colour.Blue() * math.sin((math.pi/PIPE_HEIGHT)*r))
|
|
dc.SetPen(wx.Pen(wx.Colour(red, green, blue)))
|
|
dc.DrawLine(x, y+r, x+w, y+r)
|
|
|
|
|
|
def DrawProgressBar(self, dc, x, y, w, h, percent):
|
|
"""
|
|
Draws a progress bar in the (x,y,w,h) box that represents a progress of
|
|
'percent'. The progress bar is only horizontal and it's height is constant
|
|
(PIPE_HEIGHT). The 'h' parameter is used to vertically center the progress
|
|
bar in the allotted space.
|
|
|
|
The drawing is speed-optimized. Two bitmaps are created the first time this
|
|
function runs - one for the done (green) part of the progress bar and one for
|
|
the remaining (white) part. During normal operation the function just cuts
|
|
the necessary part of the two bitmaps and draws them.
|
|
"""
|
|
|
|
# Create two pipes
|
|
if self.DONE_BITMAP is None:
|
|
self.DONE_BITMAP = wx.Bitmap(PIPE_WIDTH, PIPE_HEIGHT)
|
|
mdc = wx.MemoryDC()
|
|
mdc.SelectObject(self.DONE_BITMAP)
|
|
self.DrawHorizontalPipe(mdc, 0, 0, PIPE_WIDTH, wx.GREEN)
|
|
mdc.SelectObject(wx.NullBitmap)
|
|
|
|
self.REMAINING_BITMAP = wx.Bitmap(PIPE_WIDTH, PIPE_HEIGHT)
|
|
mdc = wx.MemoryDC()
|
|
mdc.SelectObject(self.REMAINING_BITMAP)
|
|
self.DrawHorizontalPipe(mdc, 0, 0, PIPE_WIDTH, wx.RED)
|
|
self.DrawHorizontalPipe(mdc, 1, 0, PIPE_WIDTH-1, wx.WHITE)
|
|
mdc.SelectObject(wx.NullBitmap)
|
|
|
|
# Center the progress bar vertically in the box supplied
|
|
y = y + (h - PIPE_HEIGHT)/2
|
|
|
|
if percent == 0:
|
|
middle = 0
|
|
else:
|
|
middle = (w * percent)/100
|
|
|
|
if middle == 0: # not started
|
|
bitmap = self.REMAINING_BITMAP.GetSubBitmap((1, 0, w, PIPE_HEIGHT))
|
|
dc.DrawBitmap(bitmap, x, y, False)
|
|
elif middle == w: # completed
|
|
bitmap = self.DONE_BITMAP.GetSubBitmap((0, 0, w, PIPE_HEIGHT))
|
|
dc.DrawBitmap(bitmap, x, y, False)
|
|
else: # in progress
|
|
doneBitmap = self.DONE_BITMAP.GetSubBitmap((0, 0, middle, PIPE_HEIGHT))
|
|
dc.DrawBitmap(doneBitmap, x, y, False)
|
|
remainingBitmap = self.REMAINING_BITMAP.GetSubBitmap((0, 0, w - middle, PIPE_HEIGHT))
|
|
dc.DrawBitmap(remainingBitmap, x + middle, y, False)
|
|
|
|
|
|
class UltimateRenderer_2(object):
|
|
|
|
def __init__(self, parent):
|
|
|
|
e = wx.FontEnumerator()
|
|
e.EnumerateFacenames()
|
|
fontList = e.GetFacenames()
|
|
fontList.sort()
|
|
|
|
rdn = random.randint(0, len(fontList)-1)
|
|
randomFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
randomFont.SetFaceName(fontList[rdn])
|
|
|
|
self.randomFont = randomFont
|
|
self.text = "This is my renderer"
|
|
|
|
dc = wx.ClientDC(parent)
|
|
dc.SetFont(self.randomFont)
|
|
self.width, self.height, descent, el = dc.GetFullTextExtent(self.text)
|
|
|
|
self.height += descent
|
|
|
|
|
|
def DrawSubItem(self, dc, rect, line, highlighted, enabled):
|
|
|
|
dc.SetBackgroundMode(wx.SOLID)
|
|
dc.SetBrush(wx.Brush(wx.BLACK, wx.BRUSHSTYLE_SOLID))
|
|
dc.SetPen(wx.TRANSPARENT_PEN)
|
|
dc.DrawRectangle(rect)
|
|
|
|
dc.SetBackgroundMode(wx.TRANSPARENT)
|
|
dc.SetFont(self.randomFont)
|
|
|
|
colours = [wx.RED, wx.WHITE, wx.GREEN, wx.Colour("SKY BLUE")]
|
|
w, h = dc.GetTextExtent("Hg")
|
|
x = rect.x + 1
|
|
y = rect.y + rect.height/2 - h/2
|
|
|
|
for ch in self.text:
|
|
dc.SetTextForeground(random.choice(colours))
|
|
dc.DrawText(ch, x, y)
|
|
w, h = dc.GetTextExtent(ch)
|
|
x = x + w
|
|
if x > rect.right - 5:
|
|
break
|
|
|
|
|
|
def GetLineHeight(self):
|
|
|
|
return self.height + 5
|
|
|
|
|
|
def GetSubItemWidth(self):
|
|
|
|
return self.width + 5
|
|
|
|
|
|
class UltimateRenderer_3(object):
|
|
|
|
def __init__(self):
|
|
|
|
cdb.updateColourDB()
|
|
colourList = cdb.getColourList()
|
|
lenCDB = len(colourList)
|
|
colourIndex = random.randint(0, lenCDB-1)
|
|
self.colour = colourList[colourIndex]
|
|
|
|
|
|
def DrawSubItem(self, dc, rect, line, highlighted, enabled):
|
|
|
|
centerX, centerY = rect.width/2, rect.height/2
|
|
dc.GradientFillConcentric(rect, self.colour, wx.WHITE, (centerX, centerY))
|
|
|
|
|
|
def GetLineHeight(self):
|
|
|
|
return 30
|
|
|
|
|
|
def GetSubItemWidth(self):
|
|
|
|
return 40
|
|
|
|
|
|
class UltimateHeaderRenderer(object):
|
|
|
|
def __init__(self, parent):
|
|
self._hover = False
|
|
self._pressed = False
|
|
|
|
def DrawHeaderButton(self, dc, rect, flags):
|
|
|
|
self._hover = False
|
|
self._pressed = False
|
|
|
|
color = wx.Colour(150,150,150)
|
|
if flags & wx.CONTROL_DISABLED:
|
|
color = wx.Colour(wx.WHITE)
|
|
elif flags & wx.CONTROL_SELECTED:
|
|
color = wx.Colour(wx.BLUE)
|
|
|
|
if flags & wx.CONTROL_PRESSED:
|
|
self._pressed = True
|
|
color = cutils.AdjustColour(color,-50)
|
|
elif flags & wx.CONTROL_CURRENT:
|
|
self._hover = True
|
|
color = cutils.AdjustColour(color,50)
|
|
|
|
dc.SetBrush(wx.Brush(color, wx.BRUSHSTYLE_SOLID))
|
|
dc.SetBackgroundMode(wx.SOLID)
|
|
dc.SetPen(wx.TRANSPARENT_PEN)
|
|
dc.DrawRectangle(rect)
|
|
|
|
dc.SetBackgroundMode(wx.TRANSPARENT)
|
|
|
|
|
|
def GetForegroundColour(self):
|
|
|
|
if self._hover:
|
|
return wx.Colour(30,30,30)
|
|
else:
|
|
return wx.Colour(230,230,230)
|
|
|
|
|
|
|
|
class TestUltimateListCtrl(ULC.UltimateListCtrl):
|
|
|
|
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, agwStyle=0):
|
|
|
|
ULC.UltimateListCtrl.__init__(self, parent, id, pos, size, style, agwStyle)
|
|
## listmix.TextEditMixin.__init__(self)
|
|
|
|
|
|
class UltimateListCtrlPanel(wx.Panel, listmix.ColumnSorterMixin):
|
|
|
|
def __init__(self, parent, log):
|
|
|
|
wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS|wx.SUNKEN_BORDER)
|
|
|
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
cdb.updateColourDB()
|
|
self.colourList = cdb.getColourList()
|
|
self.count = 0
|
|
self.log = log
|
|
|
|
self.il = ULC.PyImageList(16, 16)
|
|
|
|
self.idx1 = self.il.Add(images.Smiles.GetBitmap())
|
|
self.sm_up = self.il.Add(images.SmallUpArrow.GetBitmap())
|
|
self.sm_dn = self.il.Add(images.SmallDnArrow.GetBitmap())
|
|
self.il.Add(images.core.GetBitmap())
|
|
self.il.Add(images.custom.GetBitmap())
|
|
self.il.Add(images.exit.GetBitmap())
|
|
self.il.Add(images.expansion.GetBitmap())
|
|
self.il.Add(decryptedBitmap.GetBitmap())
|
|
self.il.Add(coloursBitmap.GetBitmap())
|
|
|
|
self.list = TestUltimateListCtrl(self, -1,
|
|
agwStyle=wx.LC_REPORT
|
|
#| wx.BORDER_SUNKEN
|
|
| wx.BORDER_NONE
|
|
| wx.LC_EDIT_LABELS
|
|
#| wx.LC_SORT_ASCENDING
|
|
#| wx.LC_NO_HEADER
|
|
| wx.LC_VRULES
|
|
| wx.LC_HRULES
|
|
#| wx.LC_SINGLE_SEL
|
|
| ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)
|
|
|
|
self.list.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
|
|
sizer.Add(self.list, 1, wx.EXPAND)
|
|
|
|
self.timer = wx.Timer(self, wx.ID_ANY)
|
|
|
|
self.PopulateList()
|
|
self.SetSizer(sizer)
|
|
self.SetAutoLayout(True)
|
|
|
|
self.itemDataMap = musicdata
|
|
## listmix.ColumnSorterMixin.__init__(self, 4)
|
|
|
|
self.Bind(ULC.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list)
|
|
self.Bind(ULC.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected, self.list)
|
|
self.Bind(ULC.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, self.list)
|
|
self.Bind(ULC.EVT_LIST_DELETE_ITEM, self.OnItemDelete, self.list)
|
|
self.Bind(ULC.EVT_LIST_COL_CLICK, self.OnColClick, self.list)
|
|
self.Bind(ULC.EVT_LIST_COL_RIGHT_CLICK, self.OnColRightClick, self.list)
|
|
self.Bind(ULC.EVT_LIST_COL_BEGIN_DRAG, self.OnColBeginDrag, self.list)
|
|
self.Bind(ULC.EVT_LIST_COL_DRAGGING, self.OnColDragging, self.list)
|
|
self.Bind(ULC.EVT_LIST_COL_END_DRAG, self.OnColEndDrag, self.list)
|
|
self.Bind(ULC.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.list)
|
|
self.Bind(ULC.EVT_LIST_BEGIN_DRAG, self.OnBeginDrag)
|
|
self.Bind(ULC.EVT_LIST_END_DRAG, self.OnEndDrag)
|
|
|
|
self.list.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
|
|
self.list.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
|
|
|
|
# for wxMSW
|
|
self.list.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightClick)
|
|
|
|
# for wxGTK
|
|
self.list.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
|
|
|
|
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
|
self.Bind(wx.EVT_TIMER, self.OnTimer)
|
|
|
|
|
|
def PopulateList(self):
|
|
|
|
self.list.Freeze()
|
|
|
|
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
boldfont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
boldfont.SetWeight(wx.FONTWEIGHT_BOLD)
|
|
boldfont.SetPointSize(12)
|
|
boldfont.SetUnderlined(True)
|
|
|
|
info = ULC.UltimateListItem()
|
|
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
|
|
info._image = [1, 2]
|
|
info._format = 0
|
|
info._kind = 1
|
|
info._text = "Artist\nName"
|
|
|
|
self.list.InsertColumnInfo(0, info)
|
|
|
|
info = ULC.UltimateListItem()
|
|
info._format = wx.LIST_FORMAT_RIGHT
|
|
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_FONT
|
|
info._image = []
|
|
info._text = "Title"
|
|
info._font = boldfont
|
|
|
|
self.list.InsertColumnInfo(1, info)
|
|
|
|
info = ULC.UltimateListItem()
|
|
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
|
|
info._format = 0
|
|
info._text = "Genre"
|
|
info._font = font
|
|
info._image = [3]
|
|
self.list.InsertColumnInfo(2, info)
|
|
|
|
info = ULC.UltimateListItem()
|
|
info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_FONTCOLOUR
|
|
info._format = 0
|
|
info._text = "Custom Renderer"
|
|
info._colour = wx.RED
|
|
|
|
# Add our custom renderer for the header of column 3, we can also use
|
|
# SetHeaderCustomRenderer to set the renderer for all the columns.
|
|
klass = UltimateHeaderRenderer(self)
|
|
info.SetCustomRenderer(klass)
|
|
|
|
self.list.InsertColumnInfo(3, info)
|
|
|
|
# The custom renderer can also be set for all columns on the header and/or footer
|
|
# self.list.SetHeaderCustomRenderer(klass)
|
|
|
|
# We must first have a footer in order to set its custom renderer:
|
|
# style = self.list.GetAGWWindowStyleFlag() | ULC.ULC_FOOTER
|
|
# if self.list.GetAGWWindowStyleFlag() != style:
|
|
# self.list.SetAGWWindowStyleFlag(style)
|
|
# self.list.SetFooterCustomRenderer(klass)
|
|
|
|
items = musicdata.items()
|
|
renderers = {}
|
|
|
|
for key, data in items:
|
|
if key == 3:
|
|
index = self.list.InsertImageStringItem(sys.maxsize, data[0], [3, 4, 7], it_kind=1)
|
|
elif key == 4:
|
|
dt = "\n".join(data[0].split())
|
|
index = self.list.InsertImageStringItem(sys.maxsize, dt, [self.idx1, 8, 7])
|
|
else:
|
|
index = self.list.InsertImageStringItem(sys.maxsize, data[0], self.idx1)
|
|
|
|
if key == 6:
|
|
self.list.SetStringItem(index, 1, data[1], it_kind=1)
|
|
elif key == 7:
|
|
self.list.SetStringItem(index, 1, data[1], [6, 5, 4])
|
|
elif key == 8:
|
|
dt = "\n".join(data[1].split())
|
|
self.list.SetStringItem(index, 1, dt)
|
|
else:
|
|
self.list.SetStringItem(index, 1, data[1])
|
|
|
|
it_kind = 0
|
|
if random.randint(0, 2) == 2:
|
|
# set some radiobutton-like item on the 3rd column
|
|
it_kind = 2
|
|
|
|
self.list.SetStringItem(index, 2, data[2], it_kind=it_kind)
|
|
self.list.SetStringItem(index, 3, data[3])
|
|
|
|
randomRenderer = random.randint(0, 2)
|
|
if randomRenderer == 2:
|
|
# set some custom renderers...
|
|
klass = UltimateRenderer_1(self)
|
|
renderers[index] = klass
|
|
self.list.SetItemCustomRenderer(index, 3, klass)
|
|
elif randomRenderer == 1:
|
|
klass = UltimateRenderer_2(self)
|
|
self.list.SetItemCustomRenderer(index, 3, klass)
|
|
else:
|
|
klass = UltimateRenderer_3()
|
|
self.list.SetItemCustomRenderer(index, 3, klass)
|
|
|
|
self.list.SetItemData(index, key)
|
|
|
|
self.renderers = renderers
|
|
|
|
# show how to select an item
|
|
self.list.Select(5, True)
|
|
|
|
# show how to change the colour of a couple items
|
|
item = self.list.GetItem(1)
|
|
item.SetTextColour(wx.BLUE)
|
|
pyData = datetime.date(2009, 1, 1)
|
|
item.SetPyData(pyData)
|
|
|
|
self.list.SetItem(item)
|
|
item = self.list.GetItem(4)
|
|
item.SetTextColour(wx.RED)
|
|
pyData = datetime.date(2011, 3, 2)
|
|
item.SetPyData(pyData)
|
|
self.list.SetItem(item)
|
|
|
|
# Disable one item
|
|
item = self.list.GetItem(9)
|
|
item.Enable(False)
|
|
self.list.SetItem(item)
|
|
|
|
# Set 2 hypertext items
|
|
for ids in [2, 5]:
|
|
item = self.list.GetItem(ids, 2)
|
|
item.SetHyperText(True)
|
|
self.list.SetItem(item)
|
|
|
|
# Set 2 items with widgets
|
|
item = self.list.GetItem(8, 1)
|
|
self.gauge = wx.Gauge(self.list, -1, 50, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH)
|
|
self.gauge.SetValue(20)
|
|
item.SetWindow(self.gauge)
|
|
self.list.SetItem(item)
|
|
|
|
item = self.list.GetItem(11, 0)
|
|
textctrl = wx.TextCtrl(self.list, -1, "I Am A Simple\nMultiline wx.TexCtrl", style=wx.TE_MULTILINE)
|
|
item.SetWindow(textctrl)
|
|
self.list.SetItem(item)
|
|
|
|
# Put an item with overflow
|
|
self.list.SetItemOverFlow(10, 0, True)
|
|
|
|
self.currentItem = 0
|
|
|
|
fontMask = ULC.ULC_MASK_FONTCOLOUR|ULC.ULC_MASK_FONT
|
|
fullMask = fontMask|ULC.ULC_MASK_BACKCOLOUR
|
|
|
|
customRow, customCol, colours = [0, 3], [2, 1], [wx.RED, wx.Colour("Yellow")]
|
|
|
|
for row, col, colour in zip(customRow, customCol, colours):
|
|
item = self.list.GetItem(row, col)
|
|
item.SetMask(fullMask)
|
|
item.SetTextColour(wx.GREEN)
|
|
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
font.SetWeight(wx.FONTWEIGHT_BOLD)
|
|
item.SetFont(font)
|
|
item.SetBackgroundColour(colour)
|
|
self.list.SetItem(item)
|
|
|
|
standardFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
italicFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
italicFont.SetStyle(wx.FONTSTYLE_ITALIC)
|
|
boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
|
boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
|
|
|
|
lenCDB = len(self.colourList)
|
|
|
|
for indx in range(11, 20):
|
|
for col in range(self.list.GetColumnCount()):
|
|
result = random.randint(0, 2)
|
|
colourIndex = random.randint(0, lenCDB-1)
|
|
|
|
if result == 0:
|
|
fnt = standardFont
|
|
elif result == 1:
|
|
fnt = boldFont
|
|
else:
|
|
fnt = italicFont
|
|
|
|
item = self.list.GetItem(indx, col)
|
|
item.SetMask(fontMask)
|
|
item.SetFont(fnt)
|
|
item.SetTextColour(wx.TheColourDatabase.FindColour(self.colourList[colourIndex]))
|
|
self.list.SetItem(item)
|
|
|
|
self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
|
|
self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
|
|
self.list.SetColumnWidth(2, 100)
|
|
self.list.SetColumnWidth(3, 130)
|
|
|
|
## self.list.SetColumnShown(1, False)
|
|
|
|
self.list.Thaw()
|
|
self.list.Update()
|
|
|
|
self.timer.Start(300)
|
|
|
|
## self.list.EnableSelectionVista(True)
|
|
## self.list.SetGradientStyle(1)
|
|
## self.list.SetBackgroundImage(wx.Bitmap("splash.png", wx.BITMAP_TYPE_PNG))
|
|
|
|
|
|
def ChangeStyle(self, checks):
|
|
|
|
style = 0
|
|
for check in checks:
|
|
if check.GetValue() == 1:
|
|
style = style | eval("ULC." + check.GetLabel())
|
|
|
|
if self.list.GetAGWWindowStyleFlag() != style:
|
|
self.list.SetAGWWindowStyleFlag(style)
|
|
|
|
|
|
# Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
|
|
def GetListCtrl(self):
|
|
return self.list
|
|
|
|
# Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
|
|
def GetSortImages(self):
|
|
return (self.sm_dn, self.sm_up)
|
|
|
|
|
|
def OnTimer(self, event):
|
|
|
|
for key, renderer in self.renderers.items():
|
|
renderer.UpdateValue()
|
|
self.list.RefreshItem(key)
|
|
|
|
|
|
def OnIdle(self, event):
|
|
|
|
if self.gauge:
|
|
try:
|
|
if self.gauge.IsEnabled() and self.gauge.IsShown():
|
|
self.count = self.count + 1
|
|
|
|
if self.count >= 50:
|
|
self.count = 0
|
|
|
|
self.gauge.SetValue(self.count)
|
|
|
|
except:
|
|
self.gauge = None
|
|
|
|
event.Skip()
|
|
|
|
|
|
def OnRightDown(self, event):
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
|
|
self.log.write("x, y = %s\n" % str((x, y)))
|
|
|
|
item, flags = self.list.HitTest((x, y))
|
|
|
|
if item != wx.NOT_FOUND and flags & wx.LIST_HITTEST_ONITEM:
|
|
self.list.Select(item)
|
|
|
|
event.Skip()
|
|
|
|
|
|
def getColumnText(self, index, col):
|
|
item = self.list.GetItem(index, col)
|
|
return item.GetText()
|
|
|
|
|
|
def OnItemSelected(self, event):
|
|
self.currentItem = event.Index
|
|
self.log.write("OnItemSelected: %s, %s, %s, %s\n" %(self.currentItem,
|
|
self.list.GetItemText(self.currentItem),
|
|
self.getColumnText(self.currentItem, 1),
|
|
self.getColumnText(self.currentItem, 2)))
|
|
|
|
if self.list.GetPyData(self.currentItem):
|
|
self.log.write("PYDATA = %s\n"%repr(self.list.GetPyData(self.currentItem)))
|
|
|
|
if self.currentItem == 10:
|
|
self.log.write("OnItemSelected: Veto'd selection\n")
|
|
#event.Veto() # doesn't work
|
|
# this does
|
|
self.list.SetItemState(10, 0, wx.LIST_STATE_SELECTED)
|
|
|
|
event.Skip()
|
|
|
|
|
|
def OnItemDeselected(self, evt):
|
|
item = evt.GetItem()
|
|
self.log.write("OnItemDeselected: %d\n" % evt.Index)
|
|
|
|
## # Show how to reselect something we don't want deselected
|
|
## if evt.Index == 11:
|
|
## wx.CallAfter(self.list.SetItemState, 11, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
|
|
|
|
|
|
def OnItemActivated(self, event):
|
|
self.currentItem = event.Index
|
|
self.log.write("OnItemActivated: %s\nTopItem: %s\n" %(self.list.GetItemText(self.currentItem), self.list.GetTopItem()))
|
|
|
|
def OnBeginEdit(self, event):
|
|
self.log.write("OnBeginEdit\n")
|
|
event.Allow()
|
|
|
|
def OnItemDelete(self, event):
|
|
self.log.write("OnItemDelete\n")
|
|
|
|
def OnColClick(self, event):
|
|
self.log.write("OnColClick: %d\n" % event.GetColumn())
|
|
event.Skip()
|
|
|
|
def OnColRightClick(self, event):
|
|
item = self.list.GetColumn(event.GetColumn())
|
|
self.log.write("OnColRightClick: %d %s\n" %(event.GetColumn(), (item.GetText(), item.GetAlign(),
|
|
item.GetWidth(), item.GetImage())))
|
|
|
|
def OnColBeginDrag(self, event):
|
|
self.log.write("OnColBeginDrag\n")
|
|
## Show how to not allow a column to be resized
|
|
#if event.GetColumn() == 0:
|
|
# event.Veto()
|
|
|
|
|
|
def OnColDragging(self, event):
|
|
self.log.write("OnColDragging\n")
|
|
|
|
def OnColEndDrag(self, event):
|
|
self.log.write("OnColEndDrag\n")
|
|
|
|
def OnBeginDrag(self, event):
|
|
self.log.write("OnBeginDrag\n")
|
|
|
|
|
|
def OnEndDrag(self, event):
|
|
self.log.write("OnEndDrag\n")
|
|
|
|
def OnDoubleClick(self, event):
|
|
self.log.write("OnDoubleClick item %s\n" % self.list.GetItemText(self.currentItem))
|
|
event.Skip()
|
|
|
|
def OnRightClick(self, event):
|
|
self.log.write("OnRightClick %s\n" % self.list.GetItemText(self.currentItem))
|
|
|
|
# only do this part the first time so the events are only bound once
|
|
if not hasattr(self, "popupID1"):
|
|
self.popupID1 = wx.NewIdRef()
|
|
self.popupID2 = wx.NewIdRef()
|
|
self.popupID3 = wx.NewIdRef()
|
|
self.popupID4 = wx.NewIdRef()
|
|
self.popupID5 = wx.NewIdRef()
|
|
self.popupID6 = wx.NewIdRef()
|
|
|
|
self.Bind(wx.EVT_MENU, self.OnPopupOne, id=self.popupID1)
|
|
self.Bind(wx.EVT_MENU, self.OnPopupTwo, id=self.popupID2)
|
|
self.Bind(wx.EVT_MENU, self.OnPopupThree, id=self.popupID3)
|
|
self.Bind(wx.EVT_MENU, self.OnPopupFour, id=self.popupID4)
|
|
self.Bind(wx.EVT_MENU, self.OnPopupFive, id=self.popupID5)
|
|
self.Bind(wx.EVT_MENU, self.OnPopupSix, id=self.popupID6)
|
|
|
|
# make a menu
|
|
menu = wx.Menu()
|
|
# add some items
|
|
menu.Append(self.popupID1, "FindItem tests")
|
|
menu.Append(self.popupID2, "Iterate Selected")
|
|
menu.Append(self.popupID3, "ClearAll and repopulate")
|
|
menu.Append(self.popupID4, "DeleteAllItems")
|
|
menu.Append(self.popupID5, "GetItem")
|
|
menu.Append(self.popupID6, "Edit")
|
|
|
|
# Popup the menu. If an item is selected then its handler
|
|
# will be called before PopupMenu returns.
|
|
self.PopupMenu(menu)
|
|
menu.Destroy()
|
|
|
|
|
|
def OnPopupOne(self, event):
|
|
self.log.write("Popup one")
|
|
self.log.write("FindItem: %s"%self.list.FindItem(-1, "Roxette"))
|
|
self.log.write("FindItemData: %s\n"%self.list.FindItemData(-1, 11))
|
|
|
|
def OnPopupTwo(self, event):
|
|
self.log.write("Selected items:")
|
|
index = self.list.GetFirstSelected()
|
|
|
|
while index != -1:
|
|
self.log.write(" %s: %s" % (self.list.GetItemText(index), self.getColumnText(index, 1)))
|
|
index = self.list.GetNextSelected(index)
|
|
|
|
self.log.write("\n")
|
|
|
|
def OnPopupThree(self, event):
|
|
self.log.write("Popup three")
|
|
self.list.ClearAll()
|
|
wx.CallAfter(self.PopulateList)
|
|
|
|
|
|
def OnPopupFour(self, event):
|
|
self.list.DeleteAllItems()
|
|
|
|
def OnPopupFive(self, event):
|
|
item = self.list.GetItem(self.currentItem)
|
|
self.log.write(("%s, %s, %s")%(item._text, item._itemId, self.list.GetItemData(self.currentItem)))
|
|
|
|
def OnPopupSix(self, event):
|
|
self.list.EditLabel(self.currentItem)
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
class TestFrame(wx.Frame):
|
|
|
|
def __init__(self, parent, log):
|
|
|
|
wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_REPORT mode", size=(800, 600))
|
|
|
|
splitter = wx.SplitterWindow(self, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
|
|
|
|
self.log = log
|
|
# Create the CustomTreeCtrl, using a derived class defined below
|
|
self.ulc = UltimateListCtrlPanel(splitter, self.log)
|
|
|
|
self.leftpanel = wx.ScrolledWindow(splitter, -1, style=wx.SUNKEN_BORDER)
|
|
self.leftpanel.SetScrollRate(20, 20)
|
|
width = self.PopulateLeftPanel()
|
|
|
|
# add the windows to the splitter and split it.
|
|
splitter.SplitVertically(self.leftpanel, self.ulc, width+5)
|
|
splitter.SetMinimumPaneSize(width+5)
|
|
|
|
sizer = wx.BoxSizer()
|
|
sizer.Add(splitter, 1, wx.EXPAND)
|
|
self.SetSizer(sizer)
|
|
self.SetIcon(images.Mondrian.GetIcon())
|
|
self.CenterOnScreen()
|
|
self.Show()
|
|
|
|
|
|
def PopulateLeftPanel(self):
|
|
|
|
pnl = wx.Panel(self.leftpanel)
|
|
mainsizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
staticboxstyles = wx.StaticBox(pnl, -1, "UltimateListCtrl Styles")
|
|
stylesizer = wx.StaticBoxSizer(staticboxstyles, wx.VERTICAL)
|
|
staticboxthemes = wx.StaticBox(pnl, -1, "UltimateListCtrl Themes/Gradients")
|
|
themessizer = wx.StaticBoxSizer(staticboxthemes, wx.VERTICAL)
|
|
|
|
self.ulcstyles = []
|
|
sorted_styles = []
|
|
|
|
for style in _ulcStyles:
|
|
sorted_styles.append((style, eval("ULC." + style)))
|
|
|
|
sorted_styles.sort(key=operator.itemgetter(1))
|
|
|
|
count = 0
|
|
for styleName, styleVal in sorted_styles:
|
|
|
|
if styleName in ["ULC_VIRTUAL", "ULC_TILE", "ULC_LIST", "ULC_ICON",
|
|
"ULC_SMALL_ICON", "ULC_AUTOARRANGE"]:
|
|
continue
|
|
|
|
if "SORT" in styleName or "ALIGN" in styleName or "VIEWS" in styleName:
|
|
continue
|
|
|
|
if count == 0:
|
|
tags = wx.ALL
|
|
else:
|
|
tags = wx.LEFT|wx.RIGHT|wx.BOTTOM
|
|
|
|
check = wx.CheckBox(pnl, -1, styleName)
|
|
stylesizer.Add(check, 0, tags, 3)
|
|
|
|
if self.ulc.list.HasAGWFlag(styleVal):
|
|
check.SetValue(1)
|
|
else:
|
|
check.SetValue(0)
|
|
|
|
if styleName in ["ULC_HAS_VARIABLE_ROW_HEIGHT", "ULC_REPORT"]:
|
|
check.SetValue(1)
|
|
check.Enable(False)
|
|
|
|
check.Bind(wx.EVT_CHECKBOX, self.OnCheckStyle)
|
|
self.ulcstyles.append(check)
|
|
count += 1
|
|
|
|
sizera = wx.BoxSizer(wx.HORIZONTAL)
|
|
self.checknormal = wx.CheckBox(pnl, -1, "Standard Colours")
|
|
self.checknormal.Bind(wx.EVT_CHECKBOX, self.OnCheckNormal)
|
|
sizera.Add(self.checknormal, 0, wx.ALL, 3)
|
|
|
|
sizerb = wx.BoxSizer(wx.VERTICAL)
|
|
self.checkgradient = wx.CheckBox(pnl, -1, "Gradient Theme")
|
|
self.checkgradient.Bind(wx.EVT_CHECKBOX, self.OnCheckGradient)
|
|
sizerb1 = wx.BoxSizer(wx.HORIZONTAL)
|
|
sizerb1.Add((10, 0))
|
|
self.radiohorizontal = wx.RadioButton(pnl, -1, "Horizontal", style=wx.RB_GROUP)
|
|
self.radiohorizontal.Bind(wx.EVT_RADIOBUTTON, self.OnHorizontal)
|
|
sizerb1.Add(self.radiohorizontal, 0, wx.TOP|wx.BOTTOM, 3)
|
|
sizerb2 = wx.BoxSizer(wx.HORIZONTAL)
|
|
sizerb2.Add((10, 0))
|
|
self.radiovertical = wx.RadioButton(pnl, -1, "Vertical")
|
|
self.radiovertical.Bind(wx.EVT_RADIOBUTTON, self.OnVertical)
|
|
sizerb2.Add(self.radiovertical, 0, wx.BOTTOM, 3)
|
|
sizerb3 = wx.BoxSizer(wx.HORIZONTAL)
|
|
self.firstcolour = csel.ColourSelect(pnl, -1, "First Colour",
|
|
self.ulc.list.GetFirstGradientColour())
|
|
self.secondcolour = csel.ColourSelect(pnl, -1, "Second Colour",
|
|
self.ulc.list.GetSecondGradientColour())
|
|
self.firstcolour.Bind(csel.EVT_COLOURSELECT, self.OnFirstColour)
|
|
self.secondcolour.Bind(csel.EVT_COLOURSELECT, self.OnSecondColour)
|
|
sizerb3.Add(self.firstcolour, 0, wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 3)
|
|
sizerb3.Add(self.secondcolour, 0, wx.LEFT|wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 3)
|
|
sizerb.Add(self.checkgradient, 0, wx.ALL, 3)
|
|
sizerb.Add(sizerb1, 0)
|
|
sizerb.Add(sizerb2, 0)
|
|
sizerb.Add(sizerb3, 0, wx.ALIGN_CENTER)
|
|
|
|
self.checkvista = wx.CheckBox(pnl, -1, "Windows Vista Theme")
|
|
self.checkvista.Bind(wx.EVT_CHECKBOX, self.OnVista)
|
|
|
|
themessizer.Add(sizera, 0, wx.EXPAND)
|
|
themessizer.Add(sizerb, 0, wx.EXPAND)
|
|
themessizer.Add((0, 5))
|
|
themessizer.Add(self.checkvista, 0, wx.EXPAND|wx.ALL, 3)
|
|
|
|
mainsizer.Add(stylesizer, 0, wx.EXPAND|wx.ALL, 5)
|
|
mainsizer.Add(themessizer, 0, wx.EXPAND|wx.ALL, 5)
|
|
|
|
pnl.SetSizer(mainsizer)
|
|
pnl.Fit()
|
|
|
|
swsizer = wx.BoxSizer(wx.VERTICAL)
|
|
swsizer.Add(pnl, 0, wx.EXPAND)
|
|
self.leftpanel.SetSizer(swsizer)
|
|
swsizer.Layout()
|
|
swsizer.Fit(self.leftpanel)
|
|
|
|
self.checknormal.SetValue(1)
|
|
self.radiohorizontal.Enable(False)
|
|
self.radiovertical.Enable(False)
|
|
self.firstcolour.Enable(False)
|
|
self.secondcolour.Enable(False)
|
|
|
|
return mainsizer.CalcMin().width + wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)
|
|
|
|
|
|
def OnCheckStyle(self, event):
|
|
|
|
self.ulc.ChangeStyle(self.ulcstyles)
|
|
event.Skip()
|
|
|
|
|
|
def OnCheckNormal(self, event):
|
|
|
|
self.radiohorizontal.Enable(False)
|
|
self.radiovertical.Enable(False)
|
|
self.firstcolour.Enable(False)
|
|
self.secondcolour.Enable(False)
|
|
self.checkgradient.SetValue(0)
|
|
self.checkvista.SetValue(0)
|
|
self.ulc.list.EnableSelectionGradient(False)
|
|
self.ulc.list.EnableSelectionVista(False)
|
|
event.Skip()
|
|
|
|
|
|
def OnCheckGradient(self, event):
|
|
|
|
self.radiohorizontal.Enable(True)
|
|
self.radiovertical.Enable(True)
|
|
self.firstcolour.Enable(True)
|
|
self.secondcolour.Enable(True)
|
|
self.checknormal.SetValue(0)
|
|
self.checkvista.SetValue(0)
|
|
self.ulc.list.SetGradientStyle(self.radiovertical.GetValue())
|
|
self.ulc.list.EnableSelectionVista(False)
|
|
self.ulc.list.EnableSelectionGradient(True)
|
|
|
|
event.Skip()
|
|
|
|
|
|
def OnHorizontal(self, event):
|
|
|
|
self.ulc.list.SetGradientStyle(self.radiovertical.GetValue())
|
|
event.Skip()
|
|
|
|
|
|
def OnVertical(self, event):
|
|
|
|
self.ulc.list.SetGradientStyle(self.radiovertical.GetValue())
|
|
event.Skip()
|
|
|
|
|
|
def OnFirstColour(self, event):
|
|
|
|
col1 = event.GetValue()
|
|
self.ulc.list.SetFirstGradientColour(wx.Colour(col1[0], col1[1], col1[2]))
|
|
event.Skip()
|
|
|
|
|
|
def OnSecondColour(self, event):
|
|
|
|
col1 = event.GetValue()
|
|
self.ulc.list.SetSecondGradientColour(wx.Colour(col1[0], col1[1], col1[2]))
|
|
event.Skip()
|
|
|
|
|
|
def OnVista(self, event):
|
|
|
|
self.radiohorizontal.Enable(False)
|
|
self.radiovertical.Enable(False)
|
|
self.firstcolour.Enable(False)
|
|
self.secondcolour.Enable(False)
|
|
self.checknormal.SetValue(0)
|
|
self.checkgradient.SetValue(0)
|
|
self.ulc.list.EnableSelectionGradient(False)
|
|
self.ulc.list.EnableSelectionVista(True)
|
|
|
|
event.Skip()
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
app = wx.App(0)
|
|
frame = TestFrame(None, sys.stdout)
|
|
frame.Show(True)
|
|
app.MainLoop()
|
|
|
|
|