mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-21 21:47:55 +08:00
Merged the wxPy_newswig branch into the HEAD branch (main trunk)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24541 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
+16
-122
@@ -1,125 +1,19 @@
|
||||
# Name: CDate.py
|
||||
# Purpose: Date and Calendar classes
|
||||
#
|
||||
# Author: Lorne White (email: lwhite1@planet.eon.net)
|
||||
#
|
||||
# Created:
|
||||
# Version 0.2 1999/11/08
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import time
|
||||
import wx.lib.CDate
|
||||
|
||||
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:
|
||||
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:
|
||||
def __init__(self, year, month, day):
|
||||
self.julian = julianDay(year, month, day)
|
||||
self.month = month
|
||||
self.year = year
|
||||
self.day_of_week = dayOfWeek(self.julian)
|
||||
self.days_in_month = daysPerMonth(self.month, self.year)
|
||||
__doc__ = wx.lib.CDate.__doc__
|
||||
|
||||
Date = wx.lib.CDate.Date
|
||||
FillDate = wx.lib.CDate.FillDate
|
||||
FormatDay = wx.lib.CDate.FormatDay
|
||||
FromJulian = wx.lib.CDate.FromJulian
|
||||
TodayDay = wx.lib.CDate.TodayDay
|
||||
dayOfWeek = wx.lib.CDate.dayOfWeek
|
||||
daysPerMonth = wx.lib.CDate.daysPerMonth
|
||||
isleap = wx.lib.CDate.isleap
|
||||
julianDay = wx.lib.CDate.julianDay
|
||||
leapdays = wx.lib.CDate.leapdays
|
||||
now = wx.lib.CDate.now
|
||||
|
||||
@@ -1,49 +1,9 @@
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
"""
|
||||
sorry no documentation...
|
||||
Christopher J. Fama
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.html import *
|
||||
|
||||
class wxPyClickableHtmlWindow(wxHtmlWindow):
|
||||
"""
|
||||
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(wxHtmlWindow.__init__,(self,parent,ID),kw)
|
||||
|
||||
def OnLinkClicked(self,link):
|
||||
self.link = wxTextDataObject(link.GetHref())
|
||||
if link.GetEvent().ShiftDown():
|
||||
if wxTheClipboard.Open():
|
||||
wxTheClipboard.SetData(self.link)
|
||||
wxTheClipboard.Close()
|
||||
else:
|
||||
dlg = wxMessageDialog(self,"Couldn't open clipboard!\n",wxOK)
|
||||
wxBell()
|
||||
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())
|
||||
import wx.lib.ClickableHtmlWindow
|
||||
|
||||
__doc__ = wx.lib.ClickableHtmlWindow.__doc__
|
||||
|
||||
wxPyClickableHtmlWindow = wx.lib.ClickableHtmlWindow.wxPyClickableHtmlWindow
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
|
||||
from wxPython.py.PyCrust import *
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
from wxPython.py.PyFilling import *
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
from wxPython.py.PyShell import *
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
# Change this to an ImportError after the next release
|
||||
import warnings
|
||||
warnings.warn("PyCrust has been renamed to Py. Use 'from wx import py'", stacklevel=2)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
from wxPython.py.crust import *
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
from wxPython.py.filling import *
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
from wxPython.py.shell import *
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
from wxPython.py.PyWrap import *
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.path.insert(0, os.curdir)
|
||||
main(sys.argv)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1 @@
|
||||
#
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,141 +1,14 @@
|
||||
#----------------------------------------------------------------------
|
||||
# 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
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
from wxPython.wx import *
|
||||
|
||||
try:
|
||||
import win32ui
|
||||
import pywin.mfc.activex
|
||||
import win32com.client
|
||||
except ImportError:
|
||||
raise ImportError( "ActiveXWrapper requires PythonWin. Please install the win32all-xxx.exe package.")
|
||||
|
||||
##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 = [wxWindow, pywin.mfc.activex.Control, 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, pos=wxDefaultPosition, size=wxDefaultSize, style=0):
|
||||
# init base classes
|
||||
pywin.mfc.activex.Control.__init__(self)
|
||||
wxWindow.__init__(self, parent, -1, pos, size, style|wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
|
||||
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
|
||||
EVT_SIZE(self, self.axw_OnSize)
|
||||
#EVT_ERASE_BACKGROUND(self, self.axw_OEB)
|
||||
|
||||
|
||||
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
|
||||
## anything else???
|
||||
|
||||
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.activexwrapper
|
||||
|
||||
__doc__ = wx.lib.activexwrapper.__doc__
|
||||
|
||||
MakeActiveXClass = wx.lib.activexwrapper.MakeActiveXClass
|
||||
axw_Cleanup = wx.lib.activexwrapper.axw_Cleanup
|
||||
axw_OEB = wx.lib.activexwrapper.axw_OEB
|
||||
axw_OnSize = wx.lib.activexwrapper.axw_OnSize
|
||||
axw__getattr__ = wx.lib.activexwrapper.axw__getattr__
|
||||
axw__init__ = wx.lib.activexwrapper.axw__init__
|
||||
|
||||
@@ -1,201 +1,9 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.lib.analogclock
|
||||
# Purpose: A simple analog clock window
|
||||
#
|
||||
# Author: several folks on wxPython-users
|
||||
#
|
||||
# Created: 16-April-2003
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2003 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import math, sys, string, time
|
||||
from wxPython.wx import *
|
||||
|
||||
|
||||
|
||||
class AnalogClockWindow(wxWindow):
|
||||
"""A simple analog clock window"""
|
||||
|
||||
TICKS_NONE = 0
|
||||
TICKS_SQUARE = 1
|
||||
TICKS_CIRCLE = 2
|
||||
|
||||
def __init__(self, parent, ID=-1, pos=wxDefaultPosition, size=wxDefaultSize,
|
||||
style=0, name="clock"):
|
||||
# Initialize the wxWindow...
|
||||
wxWindow.__init__(self, parent, ID, pos, size, style, name)
|
||||
|
||||
# Initialize the default clock settings...
|
||||
self.minuteMarks = 60
|
||||
self.hourMarks = 12
|
||||
self.tickMarksBrushC = self.GetForegroundColour()
|
||||
self.tickMarksPenC = self.GetForegroundColour()
|
||||
self.tickMarkStyle = self.TICKS_SQUARE
|
||||
|
||||
# Make an initial bitmap for the face, it will be updated and
|
||||
# painted at the first EVT_SIZE event.
|
||||
W, H = size
|
||||
self.faceBitmap = wxEmptyBitmap(max(W,1), max(H,1))
|
||||
|
||||
# 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 = wxTimer(self)
|
||||
self.timer.Start(500)
|
||||
|
||||
# Set event handlers...
|
||||
EVT_PAINT(self, self.OnPaint)
|
||||
EVT_ERASE_BACKGROUND(self, lambda x: None)
|
||||
EVT_SIZE(self, self.OnSize)
|
||||
EVT_TIMER(self, -1, self.OnTimerExpire)
|
||||
EVT_WINDOW_DESTROY(self, self.OnQuit)
|
||||
|
||||
|
||||
def SetTickMarkStyle(self, style):
|
||||
"""
|
||||
Set the style of the marks around the edge of the clock.
|
||||
Options are TICKS_NONE, TICKS_SQUARE, and TICKS_CIRCLE
|
||||
"""
|
||||
self.tickMarkStyle = style
|
||||
|
||||
|
||||
def SetTickMarkColours(self, brushC, penC="BLACK"):
|
||||
"""
|
||||
Set the brush colour and optionally the pen colour of
|
||||
the marks around the edge of the clock.
|
||||
"""
|
||||
self.tickMarksBrushC = brushC
|
||||
self.tickMarksPenC = penC
|
||||
|
||||
SetTickMarkColour = SetTickMarkColours
|
||||
|
||||
|
||||
def SetHandsColour(self, c):
|
||||
"""An alias for SetForegroundColour"""
|
||||
self.SetForegroundColour(c) # the hands just use the foreground colour
|
||||
|
||||
|
||||
|
||||
# Using the current settings, render the points and line endings for the
|
||||
# circle inside the specified device context. In this case, the DC is
|
||||
# a memory based device context that will be blitted to the actual
|
||||
# display DC inside the OnPaint() event handler.
|
||||
def OnSize(self, event):
|
||||
# The faceBitmap init is done here, to make sure the buffer is always
|
||||
# the same size as the Window
|
||||
size = self.GetClientSize()
|
||||
self.faceBitmap = wxEmptyBitmap(size.width, size.height)
|
||||
self.DrawFace()
|
||||
|
||||
|
||||
def OnPaint(self, event):
|
||||
self.DrawHands(wxPaintDC(self))
|
||||
|
||||
|
||||
def OnQuit(self, event):
|
||||
self.timer.Stop()
|
||||
del self.timer
|
||||
|
||||
|
||||
def OnTimerExpire(self, event):
|
||||
self.DrawHands(wxClientDC(self))
|
||||
|
||||
|
||||
def DrawHands(self, drawDC):
|
||||
# Start by drawing the face bitmap
|
||||
drawDC.DrawBitmap(self.faceBitmap,0,0)
|
||||
|
||||
currentTime = time.localtime(time.time())
|
||||
hour, minutes, seconds = currentTime[3:6]
|
||||
|
||||
W,H = self.faceBitmap.GetWidth(), self.faceBitmap.GetHeight()
|
||||
centerX = W / 2
|
||||
centerY = H / 2
|
||||
|
||||
radius = min(centerX, centerY)
|
||||
hour += minutes / 60.0 # added so the hour hand moves continuously
|
||||
x, y = self.point(hour, 12, (radius * .65))
|
||||
hourX, hourY = (x + centerX), (centerY - y)
|
||||
x, y = self.point(minutes, 60, (radius * .85))
|
||||
minutesX, minutesY = (x + centerX), (centerY - y)
|
||||
x, y = self.point(seconds, 60, (radius * .85))
|
||||
secondsX, secondsY = (x + centerX), (centerY - y)
|
||||
|
||||
# Draw the hour hand...
|
||||
drawDC.SetPen(wxPen(self.GetForegroundColour(), 5, wxSOLID))
|
||||
drawDC.DrawLine(centerX, centerY, hourX, hourY)
|
||||
|
||||
# Draw the minutes hand...
|
||||
drawDC.SetPen(wxPen(self.GetForegroundColour(), 3, wxSOLID))
|
||||
drawDC.DrawLine(centerX, centerY, minutesX, minutesY)
|
||||
|
||||
# Draw the seconds hand...
|
||||
drawDC.SetPen(wxPen(self.GetForegroundColour(), 1, wxSOLID))
|
||||
drawDC.DrawLine(centerX, centerY, secondsX, secondsY)
|
||||
|
||||
|
||||
# Draw the specified set of line marks inside the clock face for the
|
||||
# hours or minutes...
|
||||
def DrawFace(self):
|
||||
backgroundBrush = wxBrush(self.GetBackgroundColour(), wxSOLID)
|
||||
drawDC = wxMemoryDC()
|
||||
drawDC.SelectObject(self.faceBitmap)
|
||||
drawDC.SetBackground(backgroundBrush)
|
||||
drawDC.Clear()
|
||||
|
||||
W,H = self.faceBitmap.GetWidth(), self.faceBitmap.GetHeight()
|
||||
centerX = W / 2
|
||||
centerY = H / 2
|
||||
|
||||
# Draw the marks for hours and minutes...
|
||||
self.DrawTimeMarks(drawDC, self.minuteMarks, centerX, centerY, 4)
|
||||
self.DrawTimeMarks(drawDC, self.hourMarks, centerX, centerY, 9)
|
||||
|
||||
|
||||
def DrawTimeMarks(self, drawDC, markCount, centerX, centerY, markSize):
|
||||
for i in range(markCount):
|
||||
x, y = self.point(i + 1, markCount, min(centerX,centerY) - 16)
|
||||
scaledX = x + centerX - markSize/2
|
||||
scaledY = centerY - y - markSize/2
|
||||
|
||||
drawDC.SetBrush(wxBrush(self.tickMarksBrushC, wxSOLID))
|
||||
drawDC.SetPen(wxPen(self.tickMarksPenC, 1, wxSOLID))
|
||||
if self.tickMarkStyle != self.TICKS_NONE:
|
||||
if self.tickMarkStyle == self.TICKS_CIRCLE:
|
||||
drawDC.DrawEllipse(scaledX - 2, scaledY, markSize, markSize)
|
||||
else:
|
||||
drawDC.DrawRectangle(scaledX - 3, scaledY, markSize, markSize)
|
||||
|
||||
|
||||
def point(self, tick, range, radius):
|
||||
angle = tick * (360.0 / range)
|
||||
radiansPerDegree = math.pi / 180
|
||||
pointX = int(round(radius * math.sin(angle * radiansPerDegree)))
|
||||
pointY = int(round(radius * math.cos(angle * radiansPerDegree)))
|
||||
return wxPoint(pointX, pointY)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
class App(wxApp):
|
||||
def OnInit(self):
|
||||
frame = wxFrame(None, -1, "AnalogClockWindow Test", size=(375,375))
|
||||
|
||||
clock = AnalogClockWindow(frame)
|
||||
clock.SetTickMarkColours("RED")
|
||||
clock.SetHandsColour("WHITE")
|
||||
clock.SetBackgroundColour("BLUE")
|
||||
|
||||
frame.Centre(wxBOTH)
|
||||
frame.Show(True)
|
||||
self.SetTopWindow(frame)
|
||||
return true
|
||||
|
||||
theApp = App(0)
|
||||
theApp.MainLoop()
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.analogclock
|
||||
|
||||
__doc__ = wx.lib.analogclock.__doc__
|
||||
|
||||
AnalogClockWindow = wx.lib.analogclock.AnalogClockWindow
|
||||
|
||||
@@ -1,91 +1,9 @@
|
||||
#----------------------------------------------------------------------
|
||||
# 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
|
||||
#----------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
from wxPython.wx import wxLayoutConstraints, wxTop, wxLeft, wxBottom, wxRight, \
|
||||
wxHeight, wxWidth
|
||||
import wx.lib.anchors
|
||||
|
||||
class LayoutAnchors(wxLayoutConstraints):
|
||||
""" A class that implements Delphi's Anchors with wxLayoutConstraints.
|
||||
__doc__ = wx.lib.anchors.__doc__
|
||||
|
||||
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):
|
||||
wxLayoutConstraints.__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, wxLeft, left,
|
||||
self.right, wxRight, right,
|
||||
self.width, wxWidth, self.centreX,
|
||||
cPos.x, cSize.x, pSize.x, parent)
|
||||
|
||||
self.setConstraintSides(self.top, wxTop, top,
|
||||
self.bottom, wxBottom, bottom,
|
||||
self.height, wxHeight, self.centreY,
|
||||
cPos.y, cSize.y, pSize.y, 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))
|
||||
LayoutAnchors = wx.lib.anchors.LayoutAnchors
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,26 +1 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
|
||||
This version of wxPyColourChooser 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.
|
||||
"""
|
||||
|
||||
from pycolourchooser import *
|
||||
|
||||
# For the American in you
|
||||
wxPyColorChooser = wxPyColourChooser
|
||||
|
||||
__all__ = [
|
||||
'canvas',
|
||||
'pycolourbox',
|
||||
'pycolourchooser',
|
||||
'pycolourslider',
|
||||
'pypalette',
|
||||
]
|
||||
#
|
||||
|
||||
@@ -1,120 +1,10 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
import wx.lib.colourchooser.canvas
|
||||
|
||||
This version of wxPyColourChooser is open source; you can redistribute it
|
||||
and/or modify it under the licensed terms.
|
||||
__doc__ = wx.lib.colourchooser.canvas.__doc__
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
from wxPython.wx import *
|
||||
|
||||
class BitmapBuffer(wxMemoryDC):
|
||||
"""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."""
|
||||
wxMemoryDC.__init__(self)
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.colour = colour
|
||||
|
||||
self.bitmap = wxEmptyBitmap(self.width, self.height)
|
||||
self.SelectObject(self.bitmap)
|
||||
|
||||
# Initialize the buffer to the background colour
|
||||
self.SetBackground(wxBrush(self.colour, wxSOLID))
|
||||
self.Clear()
|
||||
|
||||
# Make each logical unit of the buffer equal to 1 pixel
|
||||
self.SetMapMode(wxMM_TEXT)
|
||||
|
||||
def GetBitmap(self):
|
||||
"""Returns the internal bitmap for direct drawing."""
|
||||
return self.bitmap
|
||||
|
||||
class Canvas(wxWindow):
|
||||
"""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=wxDefaultPosition,
|
||||
size=wxDefaultSize,
|
||||
style=wxSIMPLE_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."""
|
||||
wxWindow.__init__(self, parent, id, pos, size, style)
|
||||
|
||||
# Perform an intial sizing
|
||||
self.ReDraw()
|
||||
|
||||
# Register event handlers
|
||||
EVT_SIZE(self, self.onSize)
|
||||
EVT_PAINT(self, self.onPaint)
|
||||
|
||||
def MakeNewBuffer(self):
|
||||
size = self.GetSizeTuple()
|
||||
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 = wxClientDC(self)
|
||||
self.Blit(dc)
|
||||
|
||||
def onPaint(self, event):
|
||||
"""Renders the off-screen buffer on-screen."""
|
||||
dc = wxPaintDC(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.GetPositionTuple()
|
||||
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
|
||||
BitmapBuffer = wx.lib.colourchooser.canvas.BitmapBuffer
|
||||
Canvas = wx.lib.colourchooser.canvas.Canvas
|
||||
|
||||
@@ -1,24 +1,8 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
import wx.lib.colourchooser.intl
|
||||
|
||||
This version of wxPyColourChooser is open source; you can redistribute it
|
||||
and/or modify it under the licensed terms.
|
||||
__doc__ = wx.lib.colourchooser.intl.__doc__
|
||||
|
||||
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('wxpycolourchooser')
|
||||
gettext.textdomain('wxpycolourchooser')
|
||||
_ = gettext.gettext
|
||||
except Exception, strerror:
|
||||
print "Warning: Couldn't import translation function: %(str)s" %{ 'str' : strerror }
|
||||
print "Defaulting to En"
|
||||
_ = lambda x: x
|
||||
|
||||
@@ -1,79 +1,9 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
import wx.lib.colourchooser.pycolourbox
|
||||
|
||||
This version of wxPyColourChooser is open source; you can redistribute it
|
||||
and/or modify it under the licensed terms.
|
||||
__doc__ = wx.lib.colourchooser.pycolourbox.__doc__
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
from wxPython.wx import *
|
||||
|
||||
class PyColourBox(wxPanel):
|
||||
"""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."""
|
||||
wxPanel.__init__(self, parent, id,
|
||||
size=wxSize(size[0], size[1]))
|
||||
|
||||
self.colour_box = wxPanel(self, -1, style=wxSIMPLE_BORDER)
|
||||
|
||||
sizer = wxGridSizer(1, 1)
|
||||
sizer.Add(self.colour_box, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_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(wxColour(*self.colour))
|
||||
|
||||
def Update(self):
|
||||
wxPanel.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 = wxColour(red, green, blue)
|
||||
self.SetBackgroundColour(new_colour)
|
||||
else:
|
||||
self.SetBackgroundColour(self.real_bg)
|
||||
self.Refresh()
|
||||
PyColourBox = wx.lib.colourchooser.pycolourbox.PyColourBox
|
||||
|
||||
@@ -1,385 +1,10 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
import wx.lib.colourchooser.pycolourchooser
|
||||
|
||||
This version of wxPyColourChooser is open source; you can redistribute it
|
||||
and/or modify it under the licensed terms.
|
||||
__doc__ = wx.lib.colourchooser.pycolourchooser.__doc__
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
import pycolourbox
|
||||
import pypalette
|
||||
import pycolourslider
|
||||
import colorsys
|
||||
from intl import _
|
||||
from wxPython.wx import *
|
||||
|
||||
class wxPyColourChooser(wxPanel):
|
||||
"""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 = [ (wxColour(255, 255, 255),
|
||||
pycolourslider.PyColourSlider.HEIGHT / 2)
|
||||
] * NO_CUSTOM_COLOURS
|
||||
last_custom = 0
|
||||
|
||||
idADD_CUSTOM = wxNewId()
|
||||
idSCROLL = wxNewId()
|
||||
|
||||
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."""
|
||||
wxPanel.__init__(self, parent, id)
|
||||
|
||||
self.basic_label = wxStaticText(self, -1, _("Basic Colours:"))
|
||||
self.custom_label = wxStaticText(self, -1, _("Custom Colours:"))
|
||||
self.add_button = wxButton(self, self.idADD_CUSTOM, _("Add to Custom Colours"))
|
||||
|
||||
EVT_BUTTON(self, self.idADD_CUSTOM, self.onAddCustom)
|
||||
|
||||
# Since we're going to be constructing widgets that require some serious
|
||||
# computation, let's process any events (like redraws) right now
|
||||
wxYield()
|
||||
|
||||
# Create the basic colours palette
|
||||
self.colour_boxs = [ ]
|
||||
colour_grid = wxGridSizer(6, 8)
|
||||
for name in self.colour_names:
|
||||
new_id = wxNewId()
|
||||
box = pycolourbox.PyColourBox(self, new_id)
|
||||
EVT_LEFT_DOWN(box.GetColourBox(), lambda x, b=box: self.onBasicClick(x, b))
|
||||
self.colour_boxs.append(box)
|
||||
colour_grid.Add(box, 0, wxEXPAND)
|
||||
|
||||
# Create the custom colours palette
|
||||
self.custom_boxs = [ ]
|
||||
custom_grid = wxGridSizer(2, 8)
|
||||
for wxcolour, slidepos in self.custom_colours:
|
||||
new_id = wxNewId()
|
||||
custom = pycolourbox.PyColourBox(self, new_id)
|
||||
EVT_LEFT_DOWN(custom.GetColourBox(), lambda x, b=custom: self.onCustomClick(x, b))
|
||||
custom.SetColour(wxcolour)
|
||||
custom_grid.Add(custom, 0, wxEXPAND)
|
||||
self.custom_boxs.append(custom)
|
||||
|
||||
csizer = wxBoxSizer(wxVERTICAL)
|
||||
csizer.Add(1, 25)
|
||||
csizer.Add(self.basic_label, 0, wxEXPAND)
|
||||
csizer.Add(1, 5)
|
||||
csizer.Add(colour_grid, 0, wxEXPAND)
|
||||
csizer.Add(1, 25)
|
||||
csizer.Add(self.custom_label, 0, wxEXPAND)
|
||||
csizer.Add(1, 5)
|
||||
csizer.Add(custom_grid, 0, wxEXPAND)
|
||||
csizer.Add(1, 5)
|
||||
csizer.Add(self.add_button, 0, wxEXPAND)
|
||||
|
||||
self.palette = pypalette.PyPalette(self, -1)
|
||||
self.colour_slider = pycolourslider.PyColourSlider(self, -1)
|
||||
self.slider = wxSlider(self, self.idSCROLL, 86, 0, self.colour_slider.HEIGHT - 1,
|
||||
style=wxSL_VERTICAL, size=wxSize(15, self.colour_slider.HEIGHT))
|
||||
EVT_COMMAND_SCROLL(self, self.idSCROLL, self.onScroll)
|
||||
psizer = wxBoxSizer(wxHORIZONTAL)
|
||||
psizer.Add(self.palette, 0, 0)
|
||||
psizer.Add(10, 1)
|
||||
psizer.Add(self.colour_slider, 0, wxALIGN_CENTER_VERTICAL)
|
||||
psizer.Add(self.slider, 0, wxALIGN_CENTER_VERTICAL)
|
||||
|
||||
# Register mouse events for dragging across the palette
|
||||
EVT_LEFT_DOWN(self.palette, self.onPaletteDown)
|
||||
EVT_LEFT_UP(self.palette, self.onPaletteUp)
|
||||
EVT_MOTION(self.palette, self.onPaletteMotion)
|
||||
self.mouse_down = False
|
||||
|
||||
self.solid = pycolourbox.PyColourBox(self, -1, size=wxSize(75, 50))
|
||||
slabel = wxStaticText(self, -1, _("Solid Colour"))
|
||||
ssizer = wxBoxSizer(wxVERTICAL)
|
||||
ssizer.Add(self.solid, 0, 0)
|
||||
ssizer.Add(1, 2)
|
||||
ssizer.Add(slabel, 0, wxALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
hlabel = wxStaticText(self, -1, _("H:"))
|
||||
self.hentry = wxTextCtrl(self, -1)
|
||||
self.hentry.SetSize((40, -1))
|
||||
slabel = wxStaticText(self, -1, _("S:"))
|
||||
self.sentry = wxTextCtrl(self, -1)
|
||||
self.sentry.SetSize((40, -1))
|
||||
vlabel = wxStaticText(self, -1, _("V:"))
|
||||
self.ventry = wxTextCtrl(self, -1)
|
||||
self.ventry.SetSize((40, -1))
|
||||
hsvgrid = wxFlexGridSizer(1, 6, 2, 2)
|
||||
hsvgrid.AddMany ([
|
||||
(hlabel, 0, wxALIGN_CENTER_VERTICAL), (self.hentry, 0, 0),
|
||||
(slabel, 0, wxALIGN_CENTER_VERTICAL), (self.sentry, 0, 0),
|
||||
(vlabel, 0, wxALIGN_CENTER_VERTICAL), (self.ventry, 0, 0),
|
||||
])
|
||||
|
||||
rlabel = wxStaticText(self, -1, _("R:"))
|
||||
self.rentry = wxTextCtrl(self, -1)
|
||||
self.rentry.SetSize((40, -1))
|
||||
glabel = wxStaticText(self, -1, _("G:"))
|
||||
self.gentry = wxTextCtrl(self, -1)
|
||||
self.gentry.SetSize((40, -1))
|
||||
blabel = wxStaticText(self, -1, _("B:"))
|
||||
self.bentry = wxTextCtrl(self, -1)
|
||||
self.bentry.SetSize((40, -1))
|
||||
lgrid = wxFlexGridSizer(1, 6, 2, 2)
|
||||
lgrid.AddMany([
|
||||
(rlabel, 0, wxALIGN_CENTER_VERTICAL), (self.rentry, 0, 0),
|
||||
(glabel, 0, wxALIGN_CENTER_VERTICAL), (self.gentry, 0, 0),
|
||||
(blabel, 0, wxALIGN_CENTER_VERTICAL), (self.bentry, 0, 0),
|
||||
])
|
||||
|
||||
gsizer = wxGridSizer(2, 1)
|
||||
gsizer.SetVGap (10)
|
||||
gsizer.SetHGap (2)
|
||||
gsizer.Add(hsvgrid, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL)
|
||||
gsizer.Add(lgrid, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
hsizer = wxBoxSizer(wxHORIZONTAL)
|
||||
hsizer.Add(ssizer, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL)
|
||||
hsizer.Add(gsizer, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
vsizer = wxBoxSizer(wxVERTICAL)
|
||||
vsizer.Add(1, 5)
|
||||
vsizer.Add(psizer, 0, 0)
|
||||
vsizer.Add(1, 15)
|
||||
vsizer.Add(hsizer, 0, wxEXPAND)
|
||||
|
||||
sizer = wxBoxSizer(wxHORIZONTAL)
|
||||
sizer.Add(5, 1)
|
||||
sizer.Add(csizer, 0, wxEXPAND)
|
||||
sizer.Add(10, 1)
|
||||
sizer.Add(vsizer, 0, wxEXPAND)
|
||||
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 = wxTheColourDatabase.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.m_x, event.m_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.m_x, event.m_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(wxApp):
|
||||
def OnInit(self):
|
||||
frame = wxFrame(NULL, -1, 'PyColourChooser Test')
|
||||
|
||||
chooser = wxPyColourChooser(frame, -1)
|
||||
sizer = wxBoxSizer(wxVERTICAL)
|
||||
sizer.Add(chooser, 0, 0)
|
||||
frame.SetAutoLayout(True)
|
||||
frame.SetSizer(sizer)
|
||||
sizer.Fit(frame)
|
||||
|
||||
frame.Show(True)
|
||||
self.SetTopWindow(frame)
|
||||
return True
|
||||
app = App()
|
||||
app.MainLoop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
main = wx.lib.colourchooser.pycolourchooser.main
|
||||
wxPyColourChooser = wx.lib.colourchooser.pycolourchooser.wxPyColourChooser
|
||||
|
||||
@@ -1,82 +1,9 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
import wx.lib.colourchooser.pycolourslider
|
||||
|
||||
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.
|
||||
__doc__ = wx.lib.colourchooser.pycolourslider.__doc__
|
||||
|
||||
This version of wxPyColourChooser 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.
|
||||
"""
|
||||
|
||||
import canvas
|
||||
import colorsys
|
||||
from wxPython.wx import *
|
||||
|
||||
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=wxSize(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.GetPixel(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 = wxColour(int(r), int(g), int(b))
|
||||
self.buffer.SetPen(wxPen(colour, 1, wxSOLID))
|
||||
self.buffer.DrawRectangle(0, y_pos, 15, 1)
|
||||
v = v - vstep
|
||||
PyColourSlider = wx.lib.colourchooser.pycolourslider.PyColourSlider
|
||||
|
||||
@@ -1,214 +1,12 @@
|
||||
"""
|
||||
wxPyColourChooser
|
||||
Copyright (C) 2002 Michael Gilfix
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
This file is part of wxPyColourChooser.
|
||||
import wx.lib.colourchooser.pypalette
|
||||
|
||||
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.
|
||||
__doc__ = wx.lib.colourchooser.pypalette.__doc__
|
||||
|
||||
This version of wxPyColourChooser 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.
|
||||
"""
|
||||
|
||||
import canvas
|
||||
import colorsys
|
||||
import cStringIO, zlib
|
||||
from wxPython.wx import *
|
||||
|
||||
# Bitmap functions generated from img2py
|
||||
def getData():
|
||||
return zlib.decompress(
|
||||
'x\xdaUV{<\x93{\x18\x1f:\xe3\xc8Xj\xa3a\xe6R\x9db*B.3\x93\xeb\xe9\x1c\xb7\
|
||||
\xe4\xb2r9\x8c\xe5\x12e\xc9\xda\x88\x9a\xb4\x83\xcet\xa1N\xae\x85\xe3\xb2\
|
||||
\xe1,\xb7\xc2\x8a\xd0\x99D\xc8t\xdc\x86r\x1f\x96\\\x16k:\xebC\xe78\xef\xe7\
|
||||
\xf3\xbe\xbf?\xde\xf7\xf9=\xcf\xf3\xbd<\xbf\xf7WgG;\x90,L\x16\x00\x00\x80\
|
||||
\x1c\xec\xad]\xc5+[|7\xc8\x00\xc5O\xccv\xddE\xf1\xb2\x8d`\xe5\xe0&#\xbebdpT\
|
||||
\x00`\xbb\x94\x835\xc6\x8d\x989\x97\xd5N\xca\xb3\x05\xdb\xdc\x9c[\xd0\xf4\
|
||||
\xd2\xe6\x7f\xb9\xd3\xaa\xe9\x85\xd3\xd5\xd9\xbe]\xa7\xf2\xf1\xf2\x1b\xef\
|
||||
\x1b\xe6\xb7\tF\xca\t`\xef\xf9\xb5\xa2\x87\xe1\x8d\xd3\x8ft\xef\x06z\xa5\x8f\
|
||||
\xd7\x04\xf6y\xaf\xfbT\x0e\xad~\xce\xf1E\xa7\xc7\xe9\r\x8c\xab\xb7\xad_\xe4/\
|
||||
r\xf9\xb1\xbe\x97[\xb3\x88\xfcx\xd6\\\xdf\x15\x88\xca\xcc\xc0\xb0\x10\xef\
|
||||
\x81B\x9a\xf3Xzq\x1c\xb9\xa2E\xb2\xd3v\x80\xfd90@Ju[\xc3H\xe0\xea\xca\xdc\
|
||||
\xfbr\xde\xbb\xf0U\xcd\xf4\xd7\xfe\xabc\xbaN\xc2\xe3\xcc>T\xa6)(\xaa\x9f\xe7\
|
||||
\n\xaa\xe9\x00gcz\xa8Y\xb4\x8a\xc4\x0fr\x9a\x89\xe4\x9eJ\xe7\xa6z\xaf\xf7\
|
||||
\xcc\xc4\x11YI\xbfx\n@y\x04\x01\x00\nL\xd8\xb3#\xfa\x0e\'\xb7\xc1n\x98\xd3h\
|
||||
\xd5\x14\xd50\xeaA\x0bd\x8a\x16\x07\x96\xa0#\x13/!\xbf\xf1\xe5\x94)\xd5\xc3\
|
||||
\xfe\x9ej\x0c<\x8b<8\x89\x98\xcb\x9ek\x18X^\xf9\xa9\xffJ\r/\xd93\xda\xc2\xfd\
|
||||
\xfa\tt\xb9\xa3\x07\xe8u1\xc5\\O\xe9w\x94\xd6\n\x1e\xe8\xb1Q#@Z\xe2\x10\xd1\
|
||||
\xcb\xc7\x17\xbd\x9e\x94\x14~\xf9\xd6\xe0\xb1\xb3\xe8\xd8\x07E\xe4\xa6F\x87\
|
||||
\xbe6:K\xf8\xfanrn\x8b\xa4=e\xb3\x98\xf3\xc8\xde|\x0b\xf0\xb5\xb7\xfb\x0e\
|
||||
\xf5\x83:m3\xcbs\xfe*T\xc7\x89\xe1\x1a\xc8X=\xbfZ\xc4#\xd0\xee\x93d\xb6lL\
|
||||
\x15\xe4\xe3\xf7\xd8w\r\x1eK\xe0\xce\xad-`\x19g\xe6\x1f\xc8}\xcc}\xee\xecF\
|
||||
\x19_\xa6PUq\xee\xa2\x80\x1d\xbc\xf5\x14g\xe04\xa4\xc0EZB\xe6[\x1al\xb2!,\
|
||||
\xac\xa4\xf3O\x83\xa5y\x96(\xa7\xdd\xc61\x1aX\xa4X\xa8\x96\xdf2\x93\x067\x1c\
|
||||
\xf0\xed\x10\xaa\xe3\xe9\x96\xac\'l\x14\xb7\xc1\x0ed\x85\x96\xb1\x84m&d\x872\
|
||||
\x1f)\xe6wt\xd6\tV\xbe\xd4\xbe\xeaE\xcf\xaca\x92f4*Z\xce\xf8\xa0\xd9\x97\xa2\
|
||||
+\xcc\x90$\xbb\xac8\x0b\xf7\x93\xfa\xb6\xf2\x92\x9d\xa0M\xec\xc6\xaa<\x17\
|
||||
\xad\x8d\'\xc29\xd1uQjcU}\x8a\x1c\xbf\x9fg\x12\x9c\x1f\\4RZ8\xe2\xf5s@J\t\
|
||||
\xc5\rU\x92\xab\xf6B\xb3\x97\x8f^\xb8\xa5_\xd0\x98tQ\xa6KA\x12\x0c\x14gl\xc0\
|
||||
\x00\xe4f*=\xa3\x1ef\x0c\rU<\xb1sO\xaa\x0c\x82;\r)\xc8\x9c\xc0\x1f9CMch\xd4\
|
||||
\x9fn\xde/g\xc3C\xb0\xb0\x8cuS6\xf3;\x8d2q\x7fG7\x88;\xb4~9\xd5e\xa1}\x7f\
|
||||
\xd5\xa9Z\x88\x99\xaft+\xeca?\xa2qh\xaf\x8af\xbf\x82\xfe%\xac\xf6\nC_\xc6D\
|
||||
\xc6Ry\xb3\xb7N\x11"\xcfU\xbb@m\x86AY\na\xfa;\xa1\x93\x96\xf2i\xd0\x04S\x90~\
|
||||
\x1b\xb8z[1C\xde\x15w\xed\x0b\xd8\xd0\xbe\\\x19\x84\x84\xfe\x1bE\re\xda\x1az\
|
||||
6\xe6\xbe!+\x86V\xbd\xfb\xc3\xfb\xd9[\xff\xc0\x8c\xc5\nH<\x82U#2S\t\xc8\x1en\
|
||||
\xa7\xb5E\xde\x14W\xd2w\xe3\xf0\x18\x02\xa0\xf7\xad\xb6\xb2\x96\xfb\xbbH\x02\
|
||||
\x0b\x85P\xb7\xe4\x02!\xe6a\xc4d\xe8]\x17\xa4\x8bk2G\xaf\xa2p\\\x8e\xd0\x8e\
|
||||
\t\nf\xce\xf0\x10}O\xc1\x95\x9e\x80\xa6\x91\x8d\xae0\xcf\xa0\xc7\x97-h\xc3\
|
||||
\x1f\xb8"l\x14\xcaz9\xffYl\x15.l|\xc4\x94\xdd&\x9c\x9f\xf8\xb8f7\x08cA\x1e\
|
||||
\x85\x11,\xb0\xba\xf1\x87639\xfbJ\xef~e\xf3\xdbK\xd4\xe7\xec\xa5\x92\x17\xf7\
|
||||
\x1aO\xe3*\xd5\xf3\xcbA\xef\xf4\xa4[\x1d\xaf\xd7>M-\xf1\xb9@\xea\x96x\xd9(\
|
||||
\x06Z\xec+J\xed\xe5\xd45\x95\xe1\xba\xeb\xf4\xa4\xa3i\xbb\x82}\xd0\xf6Lh\xe8\
|
||||
E4;0\x9aPk\x0emo~G\x04\xb6&u\xb31\x80\xdao\x01\xf5P\x1d\xd8\x05\x92qmV\xf6R\
|
||||
\x17\x89\x1a-\xf4\x15P*\xf9?|\xcea\xa9\x8f\x99~6\x92^\xf8\x03s\x11;v\xe2D\
|
||||
\xc4^\x1c>Q\xbfY\xd0n\xbaE\xc0b=\x91\x0c=[U\x86\xfb\x06\xb52\x92\x19M1uz<\
|
||||
\xb1\xa4r~4\x83E\xe2y\x08\x0f\nQ\x84\xe8\xfa\xfa\xea\x13\x0e\xd4\x95\x91\\\
|
||||
\x7f\xf6)\x08`\xb6\x89\xc5\x95^\xff\xe2\\\x03X\xe4\xbe\x88x\x8f\xe34\xb7\xe6\
|
||||
\xbe\t\xf8\\w\x9c\xd3\x1a\xee\x98\xeeW\x92\xad\x83\x99\xb6B\xcb\x8f\xbdD\x86\
|
||||
\xc6\xe3\xab\x1b\xb2\xdf\x08:9\xbc\x9e\xf3\xf9h\xd1\xec\xd98\xc8%\x0b\x87c\
|
||||
\xb8\xbc\x0f\xad\x89\xca\xa5\x94J\xa9\x88j\x1ddo\x91u\x84\xf3\xcd\xea\xc5\
|
||||
\xf6\x99\xab\xe0\xd7-\x92\xff:\xe6)T\x07\x0bd\x1b\xa9+9\xa4\x86\xec2F\xa1\
|
||||
\xa6\x7f\xbc\xd1C\x9e\xf4=D\x12\xa2\x07\x94\t\xb1\xe8\xb5\xfb\x94\x14q~R\xa1\
|
||||
\xe6Y<\xad\xcb\x94j\xbc\xb3##\x0f\xd0 \xbf\xc9\x01\xf8\xad\xb8V\x82sdO7\xbd\
|
||||
\xbe\xd5Bd\x9f\xc0m#\xd4h<j\xf5*\x84\x86VKt\x0c4\xc1QkD\xbd\xee\xd0\xdc\xcc\
|
||||
\xad\xc5bN\'\x8f\x1b\x92\x95\x8e\xdf,\xb1\xfa\xe0\xc7f\xd5\xc7\x95\xd1&\xe06\
|
||||
\xcb\xb4t/\xa0KTj\xd0\xe2\xfb\xd2\xc3!\xf1\xcb?\r7_\x14K$xs(\xfa}~\xe2\xd9\
|
||||
\xe5gP\xd4\xfaq\x97\xb1\x0b\xd2]\xe5|\x19o2(Vm\xfe>\xe5\x13jZ\xdan\x98\xf3\
|
||||
\xe4:\x1ep\x93B\xec6?\tO\x0eaB\x99>\xc6Zkr\xcf!\x1b\x84|\xb5\xdb\x8b*O\xb4\
|
||||
\xe7\x14Ko\xa0\x93\xecmq\xd7\xf0\xbd\x12\x07\x8d\x95\xd7\x7f\xf5&\xb8bmj\xda\
|
||||
/&`>e\xeb\xfc\x14a\x19\x94S\x7f\xd2\xb5:\x8c\x04\x8f\x91\x03\xc2Q\x0e\xff{\
|
||||
\x93\xc7\xea\xd6\xbb\x1b\x0e7\xe7E\xa6\xae\x9d\xc6\x85%\x9e\xfbnc\xe3\xff\
|
||||
\xd4\xa2`9\x13\xa3\x97\x9e\xa4\x9b\x06\xa5\x9f\xec\x9f\x1a\x0c\xf0\xfe\xcd\
|
||||
\x021\x9b\x0cM\xc06\xfd u:\xe7:g\x02\xc1r\x926\x9b\x7f\xe2\xf9\xe3\xed\xf1qU\
|
||||
\xbe\xbf\xe8\x91\t\x0c0\xfb-\xe5%d\xef\x19v\x966\xec\xaaB\xe2`N[\x8c\xda\x98\
|
||||
\xf4\xb4\x83\x13\xcc\x8a\x83\x81\xa3\x91%\xdb\xad\xab\xff\x87\xe1\xba\xda\
|
||||
\xb5\xdb\xf0\x17\xfd\xf4F\x18KTNH\xf5J\xbc\x97\xdfB:\xa7\x96\xdf/k\x1c\xeaF_\
|
||||
\x8c\xfc\xdfap\x1e\x99\xae8\x94b\xa1t<\xb54.3c\xd9\xe8y=u9FM;D\xa6\xc0\xea~\
|
||||
\x0f"O\xee\x81\xdc\xa3\xb2\x1a\xa0\xa7\x02\xb9\x7f>\xfdg\x974\xc8\x0b\xbaU6P\
|
||||
\xe7\x14\xd8\xd5 \x90\xbc\x0b\xf0\xb7\xc4\x7f\x08\xfaPl\xf5\xa7\x96\xac\xc2\
|
||||
\x0f*\x05\xf3\x83\xe8\xce\xa7\xc4\x8c\xdbX\xa4U\x9b\xeeW\xe9\xf1\xbf\xa4Q#\
|
||||
\xcbDQ\x18h\x02\xca\'\xca\xee),1"\x8d\xfb<\x15\xafl\xb8\xb3z\x18\x18\xaf\xb6\
|
||||
I$\xa2\xbc\xe5\xe5J\xbe\x00\r\x08&<\x0eK\x98\x0e.[\xd1\xea`\xa9\xe2\x96\xae-\
|
||||
d9%\xc0 \x85\xc5{c_\x03x\xaf\x8f\x98P= 0\x8e\xff\xaa\xf5>7\xfeO\x7f\x1b\xcbm\
|
||||
\xb1W\xa7\t\x9b\xe1w\x02\xc5\xb5\x9fM/\x8d\xab\xe4u\r\x06\xa0\xd6\xc9\xb5\
|
||||
\xf2\xb7J\x01\xda<\r\x9f\xd1\x06\x03\xea>\xab\x9d\xe6\xde\xb4\xbb\xb1\xc6\
|
||||
\xa3EP\x1e\x17\x16\xf2\x1c\xa7\x823\xa7\xcc~\xd1\xdb\xb2\xcb\xbd\xe1\xdb\xf0\
|
||||
W(,\xe9XD)3I\xc4\x15z_\x98\x8b\xb2v\xdb\x13\xd0\xb8\xf3U"\xb713\xaf\xa0\x1dC\
|
||||
j\x0b\xb0\xf9\xfd\xef\x0ex\xd7l\xa5\xc1\xf7Z\xd2\x12\x1f\xbe\r\x87Shjm\xe3\
|
||||
\x1c\x92\xbc\xc7^\x9e\xe5\x84\xf9\xb8\xcb\x88+\x12\xb4M\xee\xb0\xbb\xcd\xc4\
|
||||
\x9c\xc7V\x1f\xde\x1b\x02\xb0!\x0c\xbeY&\xf6\xe9\xdd[u:0\x0f)(\xc5g\n\xd5\
|
||||
\xb6\xcc\xf0st\n\x113\x81Q\xcc\xef\xaa\x1b\x9a#\xad|\x12\x98\xd8\xf7"\xa2\
|
||||
\xa2\xd7\xdbwz+\x08\xb8\x0c\x9d&mZ\\-<\xbaG6j\x9cy@\x8ah\x10@\x8e\xd9\x12\
|
||||
\x9dK\x00\xf3\xabdo\x1f\x8b\x80\x9c\xf7i^#\xc1X\x7f-\x13R](\x17\xa0\x89p\x9c\
|
||||
L\x1a\xc5\x9c\x88U\xde\xc7\x9d\xd04\x04\x8en\x11\x8112\xbd\xf6J\x96wP\x06\
|
||||
\xcd\xa9x\x08\xf7\xc3\xfc\x0e\xceE\xef\xf9j\xd50\x19~\x02~\xf7C\x13\xae\xd8\
|
||||
\xea\x8e\xc9\x8c\xafpU\xc8\x8d\xaa\xe5\x88Q\xfan\x93\xf7\xf0(\xb0\x93\xf5NH\
|
||||
\x1f\xae\xc5\xf8\xaa\x97F4\x19;\x19\xe4=\x89\xe0\xae\x15\xc9\xb6\xfe\xe2\xce\
|
||||
\x1e\xca\xe6\x1a\n<\t\xa9].x\x03\xfd\x1c\x86Fd?\xbd\x17|z\x03\xa8\xafX[N"|\
|
||||
\x16\xa3#\x0e\x92\xf0h{^+K\x04/!\x8f\xac\xf4\xe4\xbbH\xa9.\x85q\xdd\x93\xc7\
|
||||
\xbb`\x96\xbb\xb5\xefQ\xdc\x9ch+G\xf8\xbf\xf6b\xdc\xfbww\xcf\xc7\x85\xf7\n@\
|
||||
\x8d[\xdc\x1b\x8e\xd5\x85\x1c\xf0@JG\x08\xc9;\n\xfb\x9dX\xc5\x8e\t\\\xb3g#\
|
||||
\xa0\xa2\xb7`\n\x96\x116?\xda\x83\xea\xa1\x7f.Y\x9f\xcb\xda_\x8c\xe9\x01s\
|
||||
\x0f\xf6\x03\xb7:\xa0\xc6\x94\xaat\xc4\x96r\x1c\x12\x06\x1dZ\xf7\x10V\xd5\
|
||||
\x088\x02N\xc6\xcc\x05y\xd7\xc0T\x07,c\xea\xb2\xcf\xc7=>y\x87M_\x9a\x86\x12\
|
||||
\xa5\x92\x83\n_"\x84\xff\x8b7\x95\xfeu\x02\x9c\xf7\xe4\xfacQyo\xda\xbb\t\xed\
|
||||
\xdeS\xd3\xb7\x04/j\xdb\x96\xae\xec\xd3\x01\xb8P\x8ap\x8c7\x88\xc2\xa8\xfd\
|
||||
\x1d\xd5\xd1=\xab$*\x8c\x9dd\xacu\x07\xe3\xa6X\xed\x1d\xb9eHd@\x8f\xb7\xd4V\
|
||||
\xdc\x95\x0f\xa91\xba\xe3s?\n\x12\xf2\x97\xefh\xf4\x1d\x89\x04\xccC)\x8f\x83\
|
||||
\xbf\x84\xd5\xe0A\xb7\xccC\xf9\xc3fGA\x92\xe4\x12\x89\x03\x14bb\xdfe\xd9\x7f\
|
||||
\x0f\x86\xc6R\xf9wC\x114\xe0\xdd\xae9\xc9ef\x92\xb6\x12\x1eU\'ZW\xa2\xe9\xa7\
|
||||
4\x15\xfdb\nr\x17\xf1\xe15IkA\xe5\x12aM[&\x93T\x16\xa5\x92x\xf8\xc3\xd4\xca\
|
||||
\xd8[\x96]wPNO\t!5\xaf&\xfarlLC\xdd\x00\xdd\x8e\x13qc\xea&]nAb\x8b1>)9\x047\
|
||||
\xc5\x8e\x1a\xd5\x84\x8b\x7f\x8f\x01\x0e6\x8e\xd6eV~W\xff\x01[x\x1b=' )
|
||||
|
||||
def getBitmap():
|
||||
return wxBitmapFromImage(getImage())
|
||||
|
||||
def getImage():
|
||||
stream = cStringIO.StringIO(getData())
|
||||
return wxImageFromStream(stream)
|
||||
|
||||
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
|
||||
self.palette = getBitmap ()
|
||||
canvas.Canvas.__init__ (self, parent, id, size=wxSize(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.GetPixel(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 = wxColour(0, 0, 0)
|
||||
self.buffer.SetPen(wxPen(colour, 1, wxSOLID))
|
||||
self.buffer.SetBrush(wxBrush(colour, wxTRANSPARENT))
|
||||
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 = wxColour(int(r * 255.0), int(g * 255.0), int(b * 255.0))
|
||||
self.buffer.SetPen(wxPen(colour, 1, wxSOLID))
|
||||
self.buffer.SetBrush(wxBrush(colour, wxSOLID))
|
||||
self.buffer.DrawRectangle(x, y,
|
||||
self.HORIZONTAL_STEP,
|
||||
self.vertical_step)
|
||||
|
||||
# this code is now simpler (and works)
|
||||
bitmap = self.buffer.GetBitmap()
|
||||
image = wxImageFromBitmap(bitmap)
|
||||
image.SaveFile (file_name, wxBITMAP_TYPE_XPM)
|
||||
PyPalette = wx.lib.colourchooser.pypalette.PyPalette
|
||||
getBitmap = wx.lib.colourchooser.pypalette.getBitmap
|
||||
getData = wx.lib.colourchooser.pypalette.getData
|
||||
getImage = wx.lib.colourchooser.pypalette.getImage
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,90 +1,11 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: ColourSelect.py
|
||||
# Purpose: Colour Box Selection Control
|
||||
#
|
||||
# Author: Lorne White, Lorne.White@telusplanet.net
|
||||
#
|
||||
# Created: Feb 25, 2001
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
from wxPython.wx import *
|
||||
import wx.lib.colourselect
|
||||
|
||||
# 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
|
||||
|
||||
EVT_COMMAND_COLOURSELECT = wxNewId()
|
||||
|
||||
class ColourSelectEvent(wxPyCommandEvent):
|
||||
def __init__(self, id, value):
|
||||
wxPyCommandEvent.__init__(self, id = id)
|
||||
self.SetEventType(EVT_COMMAND_COLOURSELECT)
|
||||
self.value = value
|
||||
|
||||
def GetValue(self):
|
||||
return self.value
|
||||
|
||||
def EVT_COLOURSELECT(win, id, func):
|
||||
win.Connect(id, -1, EVT_COMMAND_COLOURSELECT, func)
|
||||
|
||||
class ColourSelect(wxButton):
|
||||
def __init__(self, parent, id, label = "", bcolour=(0, 0, 0),
|
||||
pos = wxDefaultPosition, size = wxDefaultSize,
|
||||
callback = None):
|
||||
wxButton.__init__(self, parent, id, label, pos=pos, size=size)
|
||||
self.SetColour(bcolour)
|
||||
self.callback = callback
|
||||
EVT_BUTTON(parent, self.GetId(), self.OnClick)
|
||||
|
||||
def GetColour(self):
|
||||
return self.set_colour
|
||||
|
||||
def GetValue(self):
|
||||
return self.set_colour
|
||||
|
||||
def SetColour(self, bcolour):
|
||||
self.set_colour_val = wxColor(bcolour[0], bcolour[1], bcolour[2])
|
||||
self.SetBackgroundColour(self.set_colour_val)
|
||||
avg = reduce(lambda a, b: a + b, bcolour) / 3
|
||||
fcolour = avg > 128 and (0, 0, 0) or (255, 255, 255)
|
||||
self.SetForegroundColour(apply(wxColour, fcolour))
|
||||
self.set_colour = bcolour
|
||||
|
||||
def SetValue(self, bcolour):
|
||||
self.SetColour(bcolour)
|
||||
|
||||
def OnChange(self):
|
||||
wxPostEvent(self, ColourSelectEvent(self.GetId(), self.GetValue()))
|
||||
if self.callback is not None:
|
||||
self.callback()
|
||||
|
||||
def OnClick(self, event):
|
||||
data = wxColourData()
|
||||
data.SetChooseFull(True)
|
||||
data.SetColour(self.set_colour_val)
|
||||
dlg = wxColourDialog(self.GetParent(), data)
|
||||
changed = dlg.ShowModal() == wxID_OK
|
||||
if changed:
|
||||
data = dlg.GetColourData()
|
||||
self.SetColour(data.GetColour().Get())
|
||||
dlg.Destroy()
|
||||
|
||||
if changed:
|
||||
self.OnChange() # moved after dlg.Destroy, since who knows what the callback will do...
|
||||
__doc__ = wx.lib.colourselect.__doc__
|
||||
|
||||
ColourSelect = wx.lib.colourselect.ColourSelect
|
||||
ColourSelectEvent = wx.lib.colourselect.ColourSelectEvent
|
||||
EVT_COLOURSELECT = wx.lib.colourselect.EVT_COLOURSELECT
|
||||
|
||||
@@ -1,385 +1,27 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.lib.dialogs
|
||||
# Purpose: wxScrolledMessageDialog, wxMultipleChoiceDialog 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
|
||||
#----------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
from wxPython import wx
|
||||
from layoutf import Layoutf
|
||||
import wx.lib.dialogs
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
__doc__ = wx.lib.dialogs.__doc__
|
||||
|
||||
class wxScrolledMessageDialog(wx.wxDialog):
|
||||
def __init__(self, parent, msg, caption, pos = wx.wxDefaultPosition, size = (500,300)):
|
||||
wx.wxDialog.__init__(self, parent, -1, caption, pos, size)
|
||||
x, y = pos
|
||||
if x == -1 and y == -1:
|
||||
self.CenterOnScreen(wx.wxBOTH)
|
||||
text = wx.wxTextCtrl(self, -1, msg, wx.wxDefaultPosition,
|
||||
wx.wxDefaultSize,
|
||||
wx.wxTE_MULTILINE | wx.wxTE_READONLY)
|
||||
ok = wx.wxButton(self, wx.wxID_OK, "OK")
|
||||
text.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)))
|
||||
ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self,)))
|
||||
self.SetAutoLayout(1)
|
||||
self.Layout()
|
||||
|
||||
|
||||
class wxMultipleChoiceDialog(wx.wxDialog):
|
||||
def __init__(self, parent, msg, title, lst, pos = wx.wxDefaultPosition,
|
||||
size = (200,200), style = wx.wxDEFAULT_DIALOG_STYLE):
|
||||
wx.wxDialog.__init__(self, parent, -1, title, pos, size, style)
|
||||
x, y = pos
|
||||
if x == -1 and y == -1:
|
||||
self.CenterOnScreen(wx.wxBOTH)
|
||||
dc = wx.wxClientDC(self)
|
||||
height = 0
|
||||
for line in msg.splitlines():
|
||||
height = height + dc.GetTextExtent(line)[1] + 2
|
||||
stat = wx.wxStaticText(self, -1, msg)
|
||||
self.lbox = wx.wxListBox(self, 100, wx.wxDefaultPosition,
|
||||
wx.wxDefaultSize, lst, wx.wxLB_MULTIPLE)
|
||||
ok = wx.wxButton(self, wx.wxID_OK, "OK")
|
||||
cancel = wx.wxButton(self, wx.wxID_CANCEL, "Cancel")
|
||||
stat.SetConstraints(Layoutf('t=t10#1;l=l5#1;r=r5#1;h!%d' % (height,),
|
||||
(self,)))
|
||||
self.lbox.SetConstraints(Layoutf('t=b10#2;l=l5#1;r=r5#1;b=t5#3',
|
||||
(self, stat, ok)))
|
||||
ok.SetConstraints(Layoutf('b=b5#1;x%w25#1;w!80;h!25', (self,)))
|
||||
cancel.SetConstraints(Layoutf('b=b5#1;x%w75#1;w!80;h!25', (self,)))
|
||||
self.SetAutoLayout(1)
|
||||
self.lst = lst
|
||||
self.Layout()
|
||||
|
||||
def GetValue(self):
|
||||
return self.lbox.GetSelections()
|
||||
|
||||
def GetValueString(self):
|
||||
sel = self.lbox.GetSelections()
|
||||
val = []
|
||||
for i in sel:
|
||||
val.append(self.lst[i])
|
||||
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.wxID_OK, wx.wxID_YES)
|
||||
self.returnedString = returnedString(returned)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.__dict__)
|
||||
|
||||
def returnedString(ret):
|
||||
if ret == wx.wxID_OK:
|
||||
return "Ok"
|
||||
elif ret == wx.wxID_CANCEL:
|
||||
return "Cancel"
|
||||
elif ret == wx.wxID_YES:
|
||||
return "Yes"
|
||||
elif ret == wx.wxID_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.wxDialog(parent, -1, "Find", wx.wxDefaultPosition, wx.wxSize(370, 120))
|
||||
|
||||
wx.wxStaticText(dlg, -1, 'Find what:', wx.wxPoint(7, 10))
|
||||
wSearchText = wx.wxTextCtrl(dlg, -1, searchText,
|
||||
wx.wxPoint(70, 7), wx.wxSize(195, -1))
|
||||
wSearchText.SetValue(searchText)
|
||||
wx.wxButton(dlg, wx.wxID_OK, "Find Next", wx.wxPoint(280, 5), wx.wxDefaultSize).SetDefault()
|
||||
wx.wxButton(dlg, wx.wxID_CANCEL, "Cancel", wx.wxPoint(280, 35), wx.wxDefaultSize)
|
||||
wWholeWord = wx.wxCheckBox(dlg, -1, 'Match whole word only',
|
||||
wx.wxPoint(7, 35), wx.wxDefaultSize, wx.wxNO_BORDER)
|
||||
if wholeWordsOnly:
|
||||
wWholeWord.SetValue(1)
|
||||
wCase = wx.wxCheckBox(dlg, -1, 'Match case',
|
||||
wx.wxPoint(7, 55), wx.wxDefaultSize, wx.wxNO_BORDER)
|
||||
if caseSensitive:
|
||||
wCase.SetValue(1)
|
||||
wSearchText.SetSelection(0, len(wSearchText.GetValue()))
|
||||
wSearchText.SetFocus()
|
||||
|
||||
result = DialogResults(dlg.ShowModal())
|
||||
result.text = wSearchText.GetValue()
|
||||
result.wholeword = wWholeWord.GetValue()
|
||||
result.casesensitive = wCase.GetValue()
|
||||
dlg.Destroy()
|
||||
return result
|
||||
|
||||
|
||||
def colorDialog(parent=None, colorData=None, color=None):
|
||||
if colorData:
|
||||
dialog = wx.wxColourDialog(parent, colorData)
|
||||
else:
|
||||
dialog = wx.wxColourDialog(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.wxColourDialog(parent, colourData)
|
||||
else:
|
||||
dialog = wx.wxColourDialog(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.wxFontData()
|
||||
if font is not None:
|
||||
aFontData.SetInitialFont(font)
|
||||
dialog = wx.wxFontDialog(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.wxOK | wx.wxCANCEL):
|
||||
dialog = wx.wxTextEntryDialog(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.wxOK | wx.wxCANCEL | wx.wxCENTRE,
|
||||
pos=wx.wxDefaultPosition):
|
||||
dialog = wx.wxMessageDialog(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.wxDefaultPosition):
|
||||
return messageDialog(parent, message, title, wx.wxICON_EXCLAMATION | wx.wxOK, pos)
|
||||
|
||||
|
||||
def scrolledMessageDialog(parent=None, message='', title='', pos=wx.wxDefaultPosition, size=(500,300)):
|
||||
dialog = wxScrolledMessageDialog(parent, message, title, pos, size)
|
||||
result = DialogResults(dialog.ShowModal())
|
||||
dialog.Destroy()
|
||||
return result
|
||||
|
||||
|
||||
def fileDialog(parent=None, title='Open', directory='', filename='', wildcard='*.*',
|
||||
style=wx.wxOPEN | wx.wxMULTIPLE):
|
||||
dialog = wx.wxFileDialog(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.wxOPEN | wx.wxMULTIPLE):
|
||||
return fileDialog(parent, title, directory, filename, wildcard, style)
|
||||
|
||||
|
||||
def saveFileDialog(parent=None, title='Save', directory='', filename='',
|
||||
wildcard='All Files (*.*)|*.*',
|
||||
style=wx.wxSAVE | wx.wxHIDE_READONLY | wx.wxOVERWRITE_PROMPT):
|
||||
return fileDialog(parent, title, directory, filename, wildcard, style)
|
||||
|
||||
|
||||
def dirDialog(parent=None, message='Choose a directory', path='', style=0,
|
||||
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize):
|
||||
dialog = wx.wxDirDialog(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.wxOK | wx.wxCANCEL | wx.wxCENTRE):
|
||||
dialog = wx.wxSingleChoiceDialog(parent,
|
||||
message,
|
||||
title,
|
||||
lst,
|
||||
style)
|
||||
result = DialogResults(dialog.ShowModal())
|
||||
result.selection = dialog.GetStringSelection()
|
||||
dialog.Destroy()
|
||||
return result
|
||||
|
||||
|
||||
def multipleChoiceDialog(parent=None, message='', title='', lst=[], pos=wx.wxDefaultPosition, size=(200,200)):
|
||||
dialog = wxMultipleChoiceDialog(parent, message, title, lst, pos, size)
|
||||
result = DialogResults(dialog.ShowModal())
|
||||
result.selection = dialog.GetValueString()
|
||||
dialog.Destroy()
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
class MyApp(wx.wxApp):
|
||||
|
||||
def OnInit(self):
|
||||
frame = wx.wxFrame(wx.NULL, -1, "Dialogs", size=(400, 200))
|
||||
panel = wx.wxPanel(frame, -1)
|
||||
self.panel = panel
|
||||
|
||||
frame.Show(1)
|
||||
|
||||
dialogNames = [
|
||||
'alertDialog',
|
||||
'colorDialog',
|
||||
'directoryDialog',
|
||||
'fileDialog',
|
||||
'findDialog',
|
||||
'fontDialog',
|
||||
'messageDialog',
|
||||
'multipleChoiceDialog',
|
||||
'openFileDialog',
|
||||
'saveFileDialog',
|
||||
'scrolledMessageDialog',
|
||||
'singleChoiceDialog',
|
||||
'textEntryDialog',
|
||||
]
|
||||
self.nameList = wx.wxListBox(panel, -1, (0, 0), (130, 180), dialogNames, style=wx.wxLB_SINGLE)
|
||||
wx.EVT_LISTBOX(panel, self.nameList.GetId(), self.OnNameListSelected)
|
||||
|
||||
tstyle = wx.wxTE_RICH2 | wx.wxTE_PROCESS_TAB | wx.wxTE_MULTILINE
|
||||
self.text1 = wx.wxTextCtrl(panel, -1, pos=(150, 0), size=(200, 180), style=tstyle)
|
||||
|
||||
self.SetTopWindow(frame)
|
||||
|
||||
return 1
|
||||
|
||||
def OnNameListSelected(self, evt):
|
||||
import pprint
|
||||
sel = evt.GetString()
|
||||
result = None
|
||||
if sel == 'alertDialog':
|
||||
result = alertDialog(message='Danger Will Robinson')
|
||||
elif sel == 'colorDialog':
|
||||
result = colorDialog()
|
||||
elif sel == 'directoryDialog':
|
||||
result = directoryDialog()
|
||||
elif sel == 'fileDialog':
|
||||
wildcard = "JPG files (*.jpg;*.jpeg)|*.jpeg;*.JPG;*.JPEG;*.jpg|GIF files (*.gif)|*.GIF;*.gif|All Files (*.*)|*.*"
|
||||
result = fileDialog(None, 'Open', '', '', wildcard)
|
||||
elif sel == 'findDialog':
|
||||
result = findDialog()
|
||||
elif sel == 'fontDialog':
|
||||
result = fontDialog()
|
||||
elif sel == 'messageDialog':
|
||||
result = messageDialog(None, 'Hello from Python and wxPython!',
|
||||
'A Message Box', wx.wxOK | wx.wxICON_INFORMATION)
|
||||
#wx.wxYES_NO | wx.wxNO_DEFAULT | wx.wxCANCEL | wx.wxICON_INFORMATION)
|
||||
#result = messageDialog(None, 'message', 'title')
|
||||
elif sel == 'multipleChoiceDialog':
|
||||
result = multipleChoiceDialog(None, "message", "title", ['one', 'two', 'three'])
|
||||
elif sel == 'openFileDialog':
|
||||
result = openFileDialog()
|
||||
elif sel == 'saveFileDialog':
|
||||
result = saveFileDialog()
|
||||
elif sel == 'scrolledMessageDialog':
|
||||
msg = "Can't find the file dialog.py"
|
||||
try:
|
||||
# read this source file and then display it
|
||||
import sys
|
||||
filename = sys.argv[-1]
|
||||
fp = open(filename)
|
||||
message = fp.read()
|
||||
fp.close()
|
||||
except:
|
||||
pass
|
||||
result = scrolledMessageDialog(None, message, filename)
|
||||
elif sel == 'singleChoiceDialog':
|
||||
result = singleChoiceDialog(None, "message", "title", ['one', 'two', 'three'])
|
||||
elif sel == 'textEntryDialog':
|
||||
result = textEntryDialog(None, "message", "title", "text")
|
||||
|
||||
if result:
|
||||
#self.text1.SetValue(pprint.pformat(result.__dict__))
|
||||
self.text1.SetValue(str(result))
|
||||
|
||||
app = MyApp(0)
|
||||
app.MainLoop()
|
||||
DialogResults = wx.lib.dialogs.DialogResults
|
||||
alertDialog = wx.lib.dialogs.alertDialog
|
||||
colorDialog = wx.lib.dialogs.colorDialog
|
||||
colourDialog = wx.lib.dialogs.colourDialog
|
||||
dirDialog = wx.lib.dialogs.dirDialog
|
||||
directoryDialog = wx.lib.dialogs.directoryDialog
|
||||
fileDialog = wx.lib.dialogs.fileDialog
|
||||
findDialog = wx.lib.dialogs.findDialog
|
||||
fontDialog = wx.lib.dialogs.fontDialog
|
||||
messageDialog = wx.lib.dialogs.messageDialog
|
||||
multipleChoiceDialog = wx.lib.dialogs.multipleChoiceDialog
|
||||
openFileDialog = wx.lib.dialogs.openFileDialog
|
||||
returnedString = wx.lib.dialogs.returnedString
|
||||
saveFileDialog = wx.lib.dialogs.saveFileDialog
|
||||
scrolledMessageDialog = wx.lib.dialogs.scrolledMessageDialog
|
||||
singleChoiceDialog = wx.lib.dialogs.singleChoiceDialog
|
||||
textEntryDialog = wx.lib.dialogs.textEntryDialog
|
||||
wxMultipleChoiceDialog = wx.lib.dialogs.wxMultipleChoiceDialog
|
||||
wxScrolledMessageDialog = wx.lib.dialogs.wxScrolledMessageDialog
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
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
|
||||
@@ -1,17 +1 @@
|
||||
#----------------------------------------------------------------------
|
||||
# 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
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# This file makes this directory into a Python package
|
||||
|
||||
|
||||
# import the main classes into the package namespace.
|
||||
from editor import wxEditor
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,27 +1,10 @@
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
# images converted with wxPython's img2py.py tool
|
||||
|
||||
from wxPython.wx import wxImageFromStream, wxBitmapFromImage
|
||||
import cStringIO
|
||||
|
||||
##----------- Common Functions
|
||||
|
||||
def GetBitmap(ImageData):
|
||||
return wxBitmapFromImage(GetImage(ImageData))
|
||||
|
||||
def GetImage(ImageData):
|
||||
stream = cStringIO.StringIO(ImageData)
|
||||
return wxImageFromStream(stream)
|
||||
|
||||
##----------- Image Data
|
||||
|
||||
EofImageData = \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x07\x00\x00\x00\x07\x08\x06\
|
||||
\x00\x00\x00\xc4RW\xd3\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
|
||||
\x00:IDATx\x9c]\x8e\xc1\r\x000\x08\x02\xc5\tn\xff)\xdd\xa0}\xd1`\xf9(\x9c\t\
|
||||
\n(kf\x0e \xfbN\x90\xf3\xc1\x0c\xd2\xab\xaa\x16Huv\xa4\x00\xb5\x97\x1f\xac\
|
||||
\x87\x1c\xe4\xe1\x05`2\x15\x9e\xc54\xca\xb4\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
import wx.lib.editor.images
|
||||
|
||||
__doc__ = wx.lib.editor.images.__doc__
|
||||
|
||||
GetBitmap = wx.lib.editor.images.GetBitmap
|
||||
GetImage = wx.lib.editor.images.GetImage
|
||||
|
||||
@@ -1,42 +1,10 @@
|
||||
True = 1
|
||||
False = 0
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
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
|
||||
import wx.lib.editor.selection
|
||||
|
||||
__doc__ = wx.lib.editor.selection.__doc__
|
||||
|
||||
RestOfLine = wx.lib.editor.selection.RestOfLine
|
||||
Selection = wx.lib.editor.selection.Selection
|
||||
|
||||
+10
-515
File diff suppressed because it is too large
Load Diff
@@ -1,410 +1,24 @@
|
||||
"""<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.
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
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"""
|
||||
# Copyright 2001-2003 Timothy Hochberg
|
||||
# Use as you see fit. No warantees, I cannot be help 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 = wx.NORMAL_FONT.GetPointSize()
|
||||
defaultFamily = wx.DEFAULT
|
||||
defaultStyle = wx.NORMAL
|
||||
defaultWeight = wx.NORMAL
|
||||
defaultEncoding = wx.Font_GetDefaultEncoding()
|
||||
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
|
||||
|
||||
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.TheFontList.FindOrCreateFont(font.get("size", self.defaultSize),
|
||||
font.get("family", self.defaultFamily),
|
||||
font.get("style", self.defaultStyle),
|
||||
font.get("weight", self.defaultWeight),
|
||||
encoding = 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.ThePenList.FindOrCreatePen(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()
|
||||
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():
|
||||
app = wx.PyApp()
|
||||
box = wx.BoxSizer(wx.VERTICAL)
|
||||
frame = wx.Frame(wx.NULL, -1, "FancyText demo", wx.DefaultPosition)
|
||||
frame.SetBackgroundColour("light grey")
|
||||
sft = StaticFancyText(frame, -1, __doc__)
|
||||
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()
|
||||
import wx.lib.fancytext
|
||||
|
||||
__doc__ = wx.lib.fancytext.__doc__
|
||||
|
||||
DCRenderer = wx.lib.fancytext.DCRenderer
|
||||
GetExtent = wx.lib.fancytext.GetExtent
|
||||
GetFullExtent = wx.lib.fancytext.GetFullExtent
|
||||
RenderToBitmap = wx.lib.fancytext.RenderToBitmap
|
||||
RenderToDC = wx.lib.fancytext.RenderToDC
|
||||
RenderToRenderer = wx.lib.fancytext.RenderToRenderer
|
||||
Renderer = wx.lib.fancytext.Renderer
|
||||
SizeRenderer = wx.lib.fancytext.SizeRenderer
|
||||
StaticFancyText = wx.lib.fancytext.StaticFancyText
|
||||
_addGreek = wx.lib.fancytext._addGreek
|
||||
getExtent = wx.lib.fancytext.getExtent
|
||||
iceil = wx.lib.fancytext.iceil
|
||||
iround = wx.lib.fancytext.iround
|
||||
renderToBitmap = wx.lib.fancytext.renderToBitmap
|
||||
renderToDC = wx.lib.fancytext.renderToDC
|
||||
test = wx.lib.fancytext.test
|
||||
|
||||
@@ -1,447 +1,11 @@
|
||||
#----------------------------------------------------------------------
|
||||
# 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
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
from wxPython.wx import *
|
||||
import os, types
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class FileBrowseButton(wxPanel):
|
||||
""" A control to allow the user to type in a filename
|
||||
or browse with the standard file dialog to select file
|
||||
|
||||
__init__ (
|
||||
parent, id, pos, size -- passed directly to wxPanel initialisation
|
||||
style = wxTAB_TRAVERSAL -- passed directly to wxPanel initialisation
|
||||
labelText -- Text for label to left of text field
|
||||
buttonText -- Text for button which launches the file dialog
|
||||
toolTip -- Help text
|
||||
dialogTitle -- Title used in file dialog
|
||||
startDirectory -- Default directory for file dialog startup
|
||||
fileMask -- File mask (glob pattern, such as *.*) to use in file dialog
|
||||
fileMode -- wxOPEN or wxSAVE, indicates type of file dialog to use
|
||||
changeCallback -- callback receives all > > changes in value of control
|
||||
)
|
||||
GetValue() -- retrieve current value of text control
|
||||
SetValue(string) -- set current value of text control
|
||||
label -- pointer to internal label widget
|
||||
textControl -- pointer to internal text control
|
||||
browseButton -- pointer to button
|
||||
"""
|
||||
def __init__ (self, parent, id= -1,
|
||||
pos = wxDefaultPosition, size = wxDefaultSize,
|
||||
style = wxTAB_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 = wxOPEN,
|
||||
# callback for when value changes (optional)
|
||||
changeCallback= lambda x:x
|
||||
):
|
||||
# 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
|
||||
|
||||
|
||||
# get background to match it
|
||||
try:
|
||||
self._bc = parent.GetBackgroundColour()
|
||||
except:
|
||||
pass
|
||||
|
||||
# create the dialog
|
||||
self.createDialog(parent, id, pos, size, style )
|
||||
# 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 ):
|
||||
"""Setup the graphic representation of the dialog"""
|
||||
wxPanel.__init__ (self, parent, id, pos, size, style)
|
||||
# try to set the background colour
|
||||
try:
|
||||
self.SetBackgroundColour(self._bc)
|
||||
except:
|
||||
pass
|
||||
box = wxBoxSizer(wxHORIZONTAL)
|
||||
|
||||
self.label = self.createLabel( )
|
||||
box.Add( self.label, 0, wxCENTER )
|
||||
|
||||
self.textControl = self.createTextControl()
|
||||
box.Add( self.textControl, 1, wxLEFT|wxCENTER, 5)
|
||||
|
||||
self.browseButton = self.createBrowseButton()
|
||||
box.Add( self.browseButton, 0, wxLEFT|wxCENTER, 5)
|
||||
|
||||
# add a border around the whole thing and resize the panel to fit
|
||||
outsidebox = wxBoxSizer(wxVERTICAL)
|
||||
outsidebox.Add(box, 1, wxEXPAND|wxALL, 3)
|
||||
outsidebox.Fit(self)
|
||||
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer( outsidebox )
|
||||
self.Layout()
|
||||
if type( size ) == types.TupleType:
|
||||
size = apply( wxSize, size)
|
||||
self.SetDimensions(-1, -1, size.width, size.height, wxSIZE_USE_EXISTING)
|
||||
|
||||
# if size.width != -1 or size.height != -1:
|
||||
# self.SetSize(size)
|
||||
|
||||
def SetBackgroundColour(self,color):
|
||||
wxPanel.SetBackgroundColour(self,color)
|
||||
self.label.SetBackgroundColour(color)
|
||||
|
||||
def createLabel( self ):
|
||||
"""Create the label/caption"""
|
||||
label = wxStaticText(self, -1, self.labelText, style =wxALIGN_RIGHT )
|
||||
font = label.GetFont()
|
||||
w, h, d, e = self.GetFullTextExtent(self.labelText, font)
|
||||
label.SetSize(wxSize(w+5, h))
|
||||
return label
|
||||
|
||||
def createTextControl( self):
|
||||
"""Create the text control"""
|
||||
ID = wxNewId()
|
||||
textControl = wxTextCtrl(self, ID)
|
||||
textControl.SetToolTipString( self.toolTip )
|
||||
if self.changeCallback:
|
||||
EVT_TEXT(textControl, ID, self.OnChanged)
|
||||
EVT_COMBOBOX(textControl, ID, 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"""
|
||||
ID = wxNewId()
|
||||
button =wxButton(self, ID, self.buttonText)
|
||||
button.SetToolTipString( self.toolTip )
|
||||
EVT_BUTTON(button, ID, 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
|
||||
dlg = wxFileDialog(self, self.dialogTitle, directory, current, self.fileMask, self.fileMode)
|
||||
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
self.SetValue(dlg.GetPath())
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
def GetValue (self):
|
||||
""" Convenient access to text control value """
|
||||
return self.textControl.GetValue()
|
||||
|
||||
def SetValue (self, value, callBack=1):
|
||||
""" Convenient setting of text control value """
|
||||
save = self.callCallback
|
||||
self.callCallback = callBack
|
||||
self.textControl.SetValue(value)
|
||||
self.callCallback = save
|
||||
|
||||
|
||||
def Enable (self, value):
|
||||
""" Convenient enabling/disabling of entire control """
|
||||
self.label.Enable (value)
|
||||
self.textControl.Enable (value)
|
||||
return self.browseButton.Enable (value)
|
||||
|
||||
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 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
|
||||
apply( FileBrowseButton.__init__, ( self,)+arguments, namedarguments)
|
||||
|
||||
|
||||
def createTextControl( self):
|
||||
"""Create the text control"""
|
||||
ID = wxNewId()
|
||||
textControl = wxComboBox(self, ID, style = wxCB_DROPDOWN )
|
||||
textControl.SetToolTipString( self.toolTip )
|
||||
EVT_SET_FOCUS(textControl, self.OnSetFocus)
|
||||
if self.changeCallback:
|
||||
EVT_TEXT(textControl, ID, self.changeCallback)
|
||||
EVT_COMBOBOX(textControl, ID, self.changeCallback)
|
||||
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()
|
||||
else:
|
||||
return list( self.history )
|
||||
|
||||
|
||||
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 wxPlatform == "__WXMSW__":
|
||||
def SetValue (self, value, callBack=1):
|
||||
""" Convenient setting of text control value, works
|
||||
around limitation of wxComboBox """
|
||||
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 = wxDefaultPosition, size = wxDefaultSize,
|
||||
style = wxTAB_TRAVERSAL,
|
||||
labelText = 'Select a directory:',
|
||||
buttonText = 'Browse',
|
||||
toolTip = 'Type directory name or browse to select',
|
||||
dialogTitle = '',
|
||||
startDirectory = '.',
|
||||
changeCallback = None,
|
||||
dialogClass = wxDirDialog):
|
||||
FileBrowseButton.__init__(self, parent, id, pos, size, style,
|
||||
labelText, buttonText, toolTip,
|
||||
dialogTitle, startDirectory,
|
||||
changeCallback = changeCallback)
|
||||
#
|
||||
self._dirDialog = dialogClass(self,
|
||||
message = dialogTitle,
|
||||
defaultPath = startDirectory)
|
||||
#
|
||||
def OnBrowse(self, ev = None):
|
||||
dialog = self._dirDialog
|
||||
if dialog.ShowModal() == wxID_OK:
|
||||
self.SetValue(dialog.GetPath())
|
||||
#
|
||||
def __del__(self):
|
||||
if self.__dict__.has_key('_dirDialog'):
|
||||
self._dirDialog.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( wxFrame ):
|
||||
def __init__(self, parent):
|
||||
wxFrame.__init__(self, parent, 2400, "File entry with browse", size=(500,260) )
|
||||
EVT_CLOSE(self, self.OnCloseWindow)
|
||||
panel = wxPanel (self,-1)
|
||||
innerbox = wxBoxSizer(wxVERTICAL)
|
||||
control = FileBrowseButton(
|
||||
panel,
|
||||
initialValue = "z:\\temp",
|
||||
)
|
||||
innerbox.Add( control, 0, wxEXPAND )
|
||||
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, wxEXPAND )
|
||||
middlecontrol = FileBrowseButtonWithHistory(
|
||||
panel,
|
||||
labelText = "History callback",
|
||||
initialValue = "d:\\temp",
|
||||
history = self.historyCallBack,
|
||||
changeCallback= SimpleCallback( "History callback" ),
|
||||
)
|
||||
innerbox.Add( middlecontrol, 0, wxEXPAND )
|
||||
self.bottomcontrol = control = FileBrowseButton(
|
||||
panel,
|
||||
labelText = "With Callback",
|
||||
style = wxSUNKEN_BORDER|wxCLIP_CHILDREN ,
|
||||
changeCallback= SimpleCallback( "With Callback" ),
|
||||
)
|
||||
innerbox.Add( control, 0, wxEXPAND)
|
||||
self.bottommostcontrol = control = DirBrowseButton(
|
||||
panel,
|
||||
labelText = "Simple dir browse button",
|
||||
style = wxSUNKEN_BORDER|wxCLIP_CHILDREN)
|
||||
innerbox.Add( control, 0, wxEXPAND)
|
||||
ID = wxNewId()
|
||||
innerbox.Add( wxButton( panel, ID,"Change Label", ), 1, wxEXPAND)
|
||||
EVT_BUTTON( self, ID, self.OnChangeLabel )
|
||||
ID = wxNewId()
|
||||
innerbox.Add( wxButton( panel, ID,"Change Value", ), 1, wxEXPAND)
|
||||
EVT_BUTTON( self, ID, self.OnChangeValue )
|
||||
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(wxApp):
|
||||
def OnInit(self):
|
||||
wxImage_AddHandler(wxJPEGHandler())
|
||||
wxImage_AddHandler(wxPNGHandler())
|
||||
wxImage_AddHandler(wxGIFHandler())
|
||||
frame = DemoFrame(NULL)
|
||||
#frame = RulesPanel(NULL )
|
||||
frame.Show(True)
|
||||
self.SetTopWindow(frame)
|
||||
return True
|
||||
|
||||
def test( ):
|
||||
app = DemoApp(0)
|
||||
app.MainLoop()
|
||||
print 'Creating dialog'
|
||||
test( )
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.filebrowsebutton
|
||||
|
||||
__doc__ = wx.lib.filebrowsebutton.__doc__
|
||||
|
||||
DirBrowseButton = wx.lib.filebrowsebutton.DirBrowseButton
|
||||
FileBrowseButton = wx.lib.filebrowsebutton.FileBrowseButton
|
||||
FileBrowseButtonWithHistory = wx.lib.filebrowsebutton.FileBrowseButtonWithHistory
|
||||
|
||||
@@ -1,283 +1,9 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: floatbar.py
|
||||
# Purpose: Contains floating toolbar class
|
||||
#
|
||||
# Author: Bryn Keller
|
||||
#
|
||||
# Created: 10/4/99
|
||||
#----------------------------------------------------------------------------
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
from wxPython.wx import *
|
||||
|
||||
if wxPlatform == '__WXGTK__':
|
||||
#
|
||||
# For wxGTK all we have to do is set the wxTB_DOCKABLE flag
|
||||
#
|
||||
class wxFloatBar(wxToolBar):
|
||||
def __init__(self, parent, ID,
|
||||
pos = wxDefaultPosition,
|
||||
size = wxDefaultSize,
|
||||
style = 0,
|
||||
name = 'toolbar'):
|
||||
wxToolBar.__init__(self, parent, ID, pos, size,
|
||||
style|wxTB_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 wxFloatBar(wxToolBar):
|
||||
"""
|
||||
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(wxToolBar.__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 = ""
|
||||
EVT_MOUSE_EVENTS(self, self.OnMouse)
|
||||
self.parentframe = wxPyTypeCast(args[1], 'wxFrame')
|
||||
|
||||
|
||||
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 = wxMiniFrame(NULL, -1, "TEST")
|
||||
test.SetClientSize(wxSize(0,0))
|
||||
self.titleheight = test.GetSizeTuple()[1]
|
||||
test.Destroy()
|
||||
|
||||
|
||||
def IsFloating(self):
|
||||
return self.floating
|
||||
|
||||
|
||||
def Realize(self):
|
||||
wxToolBar.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 wxPyTypeCast(self.GetParent(), 'wxFrame')
|
||||
|
||||
|
||||
## 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 = wxPyTypeCast(self.GetParent(), 'wxFrame')
|
||||
## 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 = wxPyTypeCast(self.GetParent(), 'wxFrame')
|
||||
print self.title
|
||||
if self.title:
|
||||
useStyle = wxDEFAULT_FRAME_STYLE
|
||||
else:
|
||||
useStyle = wxTHICK_FRAME
|
||||
self.floatframe = wxMiniFrame(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(wxSize(0,0))
|
||||
self.parentframe.SetSize(psize)
|
||||
self.floatframe.SetToolBar(self)
|
||||
self.oldcolor = self.GetBackgroundColour()
|
||||
|
||||
w = psize.width
|
||||
h = self.GetSize().height
|
||||
if self.title:
|
||||
h = h + self.titleheight
|
||||
self.floatframe.SetSize(wxSize(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)
|
||||
|
||||
EVT_CLOSE(self.floatframe, self.OnDock)
|
||||
#EVT_MOVE(self.floatframe, 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(wxSize(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(wxPoint(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(wxPoint(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 = wxPoint(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 = wxToolBar(self.parentframe, -1)
|
||||
print "Adding fauxbar."
|
||||
self.nullbar.Reparent(self.parentframe)
|
||||
print "Reparented."
|
||||
self.parentframe.SetToolBar(self.nullbar)
|
||||
print "Set toolbar"
|
||||
col = wxNamedColour("GREY")
|
||||
self.nullbar.SetBackgroundColour(col)
|
||||
print "Set color"
|
||||
size = self.parentframe.GetSize()
|
||||
self.parentframe.SetSize(wxSize(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(wxSize(0,0))
|
||||
self.parentframe.SetSize(size)
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.floatbar
|
||||
|
||||
__doc__ = wx.lib.floatbar.__doc__
|
||||
|
||||
wxFloatBar = wx.lib.floatbar.wxFloatBar
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.foldmenu
|
||||
|
||||
__doc__ = wx.lib.foldmenu.__doc__
|
||||
|
||||
FoldOutMenu = wx.lib.foldmenu.FoldOutMenu
|
||||
FoldOutWindow = wx.lib.foldmenu.FoldOutWindow
|
||||
@@ -1,419 +1,18 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# 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
|
||||
#----------------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.grid import wxGridPtr
|
||||
import wx.lib.gridmovers
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# event class and macors
|
||||
__doc__ = wx.lib.gridmovers.__doc__
|
||||
|
||||
|
||||
wxEVT_COMMAND_GRID_COL_MOVE = wxNewEventType()
|
||||
wxEVT_COMMAND_GRID_ROW_MOVE = wxNewEventType()
|
||||
|
||||
def EVT_GRID_COL_MOVE(win, id, func):
|
||||
win.Connect(id, -1, wxEVT_COMMAND_GRID_COL_MOVE, func)
|
||||
|
||||
def EVT_GRID_ROW_MOVE(win,id,func):
|
||||
win.Connect(id, -1, wxEVT_COMMAND_GRID_ROW_MOVE, func)
|
||||
|
||||
|
||||
class wxGridColMoveEvent(wxPyCommandEvent):
|
||||
def __init__(self, id, dCol, bCol):
|
||||
wxPyCommandEvent.__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 wxGridRowMoveEvent(wxPyCommandEvent):
|
||||
def __init__(self, id, dRow, bRow):
|
||||
wxPyCommandEvent.__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 wxGridPtr class
|
||||
|
||||
def _ColToRect(self,col):
|
||||
if self.GetNumberRows() > 0:
|
||||
rect = self.CellToRect(0,col)
|
||||
else:
|
||||
rect = wxRect()
|
||||
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
|
||||
|
||||
wxGridPtr.ColToRect = _ColToRect
|
||||
|
||||
|
||||
def _RowToRect(self,row):
|
||||
if self.GetNumberCols() > 0:
|
||||
rect = self.CellToRect(row,0)
|
||||
else:
|
||||
rect = wxRect()
|
||||
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
|
||||
|
||||
wxGridPtr.RowToRect = _RowToRect
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
class ColDragWindow(wxWindow):
|
||||
def __init__(self,parent,image,dragCol):
|
||||
wxWindow.__init__(self,parent,wxSIMPLE_BORDER)
|
||||
self.image = image
|
||||
self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
|
||||
self.ux = parent.GetScrollPixelsPerUnit()[0]
|
||||
self.moveColumn = dragCol
|
||||
|
||||
EVT_PAINT(self,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._rlSize
|
||||
x = self.GetPositionTuple()[0]
|
||||
w = self.GetSizeTuple()[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 = wxPaintDC(self)
|
||||
w,h = self.GetSize()
|
||||
dc.DrawBitmap(self.image,0,0)
|
||||
dc.SetPen(wxPen(wxBLACK,1,wxSOLID))
|
||||
dc.SetBrush(wxTRANSPARENT_BRUSH)
|
||||
dc.DrawRectangle(0,0,w,h)
|
||||
iPos = self.GetInsertionPos()
|
||||
dc.DrawLine(iPos,h - 10,iPos,h)
|
||||
|
||||
|
||||
|
||||
|
||||
class RowDragWindow(wxWindow):
|
||||
def __init__(self,parent,image,dragRow):
|
||||
wxWindow.__init__(self,parent,wxSIMPLE_BORDER)
|
||||
self.image = image
|
||||
self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
|
||||
self.uy = parent.GetScrollPixelsPerUnit()[1]
|
||||
self.moveRow = dragRow
|
||||
|
||||
EVT_PAINT(self,self.OnPaint)
|
||||
|
||||
def DisplayAt(self,x,pos):
|
||||
y = self.GetPositionTuple()[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._clSize
|
||||
y = self.GetPositionTuple()[1]
|
||||
h = self.GetSizeTuple()[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 = wxPaintDC(self)
|
||||
w,h = self.GetSize()
|
||||
dc.DrawBitmap(self.image,0,0)
|
||||
dc.SetPen(wxPen(wxBLACK,1,wxSOLID))
|
||||
dc.SetBrush(wxTRANSPARENT_BRUSH)
|
||||
dc.DrawRectangle(0,0,w,h)
|
||||
iPos = self.GetInsertionPos()
|
||||
dc.DrawLine(w - 10,iPos,w,iPos)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
class wxGridColMover(wxEvtHandler):
|
||||
def __init__(self,grid):
|
||||
wxEvtHandler.__init__(self)
|
||||
|
||||
self.grid = grid
|
||||
self.grid._rlSize = self.grid.GetRowLabelSize()
|
||||
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
|
||||
|
||||
EVT_MOTION(self,self.OnMouseMove)
|
||||
EVT_LEFT_DOWN(self,self.OnPress)
|
||||
EVT_LEFT_UP(self,self.OnRelease)
|
||||
|
||||
def OnMouseMove(self,evt):
|
||||
if self.isDragging:
|
||||
if abs(self.startX - evt.m_x) >= 3:
|
||||
self.didMove = True
|
||||
sx,y = self.grid.GetViewStart()
|
||||
w,h = self.lwin.GetClientSizeTuple()
|
||||
x = sx * self.ux
|
||||
if (evt.m_x + x) < x:
|
||||
x = evt.m_x + x
|
||||
elif evt.m_x > w:
|
||||
x += evt.m_x - w
|
||||
if x < 1: x = 0
|
||||
else: x /= self.ux
|
||||
if x != sx:
|
||||
if wxPlatform == '__WXMSW__':
|
||||
self.colWin.Show(False)
|
||||
self.grid.Scroll(x,y)
|
||||
x,y = self.lwin.ClientToScreenXY(evt.m_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 + self.grid._rlSize: px = 0 + self.grid._rlSize
|
||||
if px > w - self.colWin.GetSizeTuple()[0] + self.grid._rlSize:
|
||||
px = w - self.colWin.GetSizeTuple()[0] + self.grid._rlSize
|
||||
self.colWin.DisplayAt(px,y)
|
||||
return
|
||||
evt.Skip()
|
||||
|
||||
def OnPress(self,evt):
|
||||
self.startX = evt.m_x
|
||||
sx = self.grid.GetViewStart()[0] * self.ux
|
||||
sx -= self.grid._rlSize
|
||||
px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y)
|
||||
px,py = self.grid.ScreenToClientXY(px,py)
|
||||
if self.grid.XToEdgeOfCol(px + sx) != wxNOT_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.GetSizeTuple()
|
||||
rect.y = 0
|
||||
rect.x -= sx + self.grid._rlSize
|
||||
rect.height = size[1]
|
||||
colImg = self._CaptureImage(rect)
|
||||
self.colWin = ColDragWindow(self.grid,colImg,col)
|
||||
self.colWin.Show(False)
|
||||
self.lwin.CaptureMouse()
|
||||
|
||||
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._rlSize
|
||||
col = self.grid.XToCol(px+sx)
|
||||
if col != wxNOT_FOUND:
|
||||
self.grid.SelectCol(col,evt.m_controlDown)
|
||||
return
|
||||
else:
|
||||
bCol = self.colWin.GetInsertionColumn()
|
||||
dCol = self.colWin.GetMoveColumn()
|
||||
wxPostEvent(self,wxGridColMoveEvent(self.grid.GetId(),
|
||||
dCol,bCol))
|
||||
self.colWin.Destroy()
|
||||
evt.Skip()
|
||||
|
||||
def _CaptureImage(self,rect):
|
||||
bmp = wxEmptyBitmap(rect.width,rect.height)
|
||||
memdc = wxMemoryDC()
|
||||
memdc.SelectObject(bmp)
|
||||
dc = wxWindowDC(self.lwin)
|
||||
memdc.Blit(0,0,rect.width,rect.height,dc,rect.x,rect.y)
|
||||
memdc.SelectObject(wxNullBitmap)
|
||||
return bmp
|
||||
|
||||
|
||||
|
||||
class wxGridRowMover(wxEvtHandler):
|
||||
def __init__(self,grid):
|
||||
wxEvtHandler.__init__(self)
|
||||
|
||||
self.grid = grid
|
||||
self.grid._clSize = self.grid.GetColLabelSize()
|
||||
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
|
||||
|
||||
EVT_MOTION(self,self.OnMouseMove)
|
||||
EVT_LEFT_DOWN(self,self.OnPress)
|
||||
EVT_LEFT_UP(self,self.OnRelease)
|
||||
|
||||
def OnMouseMove(self,evt):
|
||||
if self.isDragging:
|
||||
if abs(self.startY - evt.m_y) >= 3:
|
||||
self.didMove = True
|
||||
x,sy = self.grid.GetViewStart()
|
||||
w,h = self.lwin.GetClientSizeTuple()
|
||||
y = sy * self.uy
|
||||
if (evt.m_y + y) < y:
|
||||
y = evt.m_y + y
|
||||
elif evt.m_y > h:
|
||||
y += evt.m_y - h
|
||||
if y < 1: y = 0
|
||||
else: y /= self.uy
|
||||
if y != sy:
|
||||
if wxPlatform == '__WXMSW__':
|
||||
self.rowWin.Show(False)
|
||||
self.grid.Scroll(x,y)
|
||||
x,y = self.lwin.ClientToScreenXY(0,evt.m_y)
|
||||
x,y = self.grid.ScreenToClientXY(x,y)
|
||||
if not self.rowWin.IsShown():
|
||||
self.rowWin.Show(True)
|
||||
py = y - self.cellY
|
||||
if py < 0 + self.grid._clSize: py = 0 + self.grid._clSize
|
||||
if py > h - self.rowWin.GetSizeTuple()[1] + self.grid._clSize:
|
||||
py = h - self.rowWin.GetSizeTuple()[1] + self.grid._clSize
|
||||
self.rowWin.DisplayAt(x,py)
|
||||
return
|
||||
evt.Skip()
|
||||
|
||||
def OnPress(self,evt):
|
||||
self.startY = evt.m_y
|
||||
sy = self.grid.GetViewStart()[1] * self.uy
|
||||
sy -= self.grid._clSize
|
||||
px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y)
|
||||
px,py = self.grid.ScreenToClientXY(px,py)
|
||||
if self.grid.YToEdgeOfRow(py + sy) != wxNOT_FOUND:
|
||||
evt.Skip()
|
||||
return
|
||||
|
||||
self.isDragging = True
|
||||
self.didMove = False
|
||||
row = self.grid.YToRow(py + sy)
|
||||
rect = self.grid.RowToRect(row)
|
||||
self.cellY = py + sy - rect.y
|
||||
size = self.lwin.GetSizeTuple()
|
||||
rect.x = 0
|
||||
rect.y -= sy + self.grid._clSize
|
||||
rect.width = size[0]
|
||||
rowImg = self._CaptureImage(rect)
|
||||
self.rowWin = RowDragWindow(self.grid,rowImg,row)
|
||||
self.rowWin.Show(False)
|
||||
self.lwin.CaptureMouse()
|
||||
|
||||
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._clSize
|
||||
row = self.grid.YToRow(py + sy)
|
||||
if row != wxNOT_FOUND:
|
||||
self.grid.SelectRow(row,evt.m_controlDown)
|
||||
return
|
||||
else:
|
||||
bRow = self.rowWin.GetInsertionRow()
|
||||
dRow = self.rowWin.GetMoveRow()
|
||||
wxPostEvent(self,wxGridRowMoveEvent(self.grid.GetId(),
|
||||
dRow,bRow))
|
||||
self.rowWin.Destroy()
|
||||
evt.Skip()
|
||||
|
||||
def _CaptureImage(self,rect):
|
||||
bmp = wxEmptyBitmap(rect.width,rect.height)
|
||||
memdc = wxMemoryDC()
|
||||
memdc.SelectObject(bmp)
|
||||
dc = wxWindowDC(self.lwin)
|
||||
memdc.Blit(0,0,rect.width,rect.height,dc,rect.x,rect.y)
|
||||
memdc.SelectObject(wxNullBitmap)
|
||||
return bmp
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
ColDragWindow = wx.lib.gridmovers.ColDragWindow
|
||||
EVT_GRID_COL_MOVE = wx.lib.gridmovers.EVT_GRID_COL_MOVE
|
||||
EVT_GRID_ROW_MOVE = wx.lib.gridmovers.EVT_GRID_ROW_MOVE
|
||||
RowDragWindow = wx.lib.gridmovers.RowDragWindow
|
||||
_ColToRect = wx.lib.gridmovers._ColToRect
|
||||
_RowToRect = wx.lib.gridmovers._RowToRect
|
||||
wxGridColMoveEvent = wx.lib.gridmovers.wxGridColMoveEvent
|
||||
wxGridColMover = wx.lib.gridmovers.wxGridColMover
|
||||
wxGridRowMoveEvent = wx.lib.gridmovers.wxGridRowMoveEvent
|
||||
wxGridRowMover = wx.lib.gridmovers.wxGridRowMover
|
||||
|
||||
@@ -1,267 +1,10 @@
|
||||
#----------------------------------------------------------------------
|
||||
# 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
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
In this module you will find wxGridSizer and wxFlexGridSizer. Please
|
||||
note that these sizers have since been ported to C++ 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.
|
||||
|
||||
wxGridSizer: 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.
|
||||
|
||||
wxFlexGridSizer: Derives from wxGridSizer 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.
|
||||
|
||||
See the demo for a couple examples for how to use them.
|
||||
"""
|
||||
|
||||
|
||||
from wxPython.wx import *
|
||||
|
||||
import operator
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class wxGridSizer(wxPySizer):
|
||||
def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
|
||||
wxPySizer.__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 wxSize(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 = wxPoint(x, y)
|
||||
isz = item.CalcMin()
|
||||
flag = item.GetFlag()
|
||||
|
||||
if flag & wxEXPAND or flag & wxSHAPED:
|
||||
isz = wxSize(w, h)
|
||||
else:
|
||||
if flag & wxALIGN_CENTER_HORIZONTAL:
|
||||
ipt.x = x + (w - isz.width) / 2
|
||||
elif flag & wxALIGN_RIGHT:
|
||||
ipt.x = x + (w - isz.width)
|
||||
|
||||
if flag & wxALIGN_CENTER_VERTICAL:
|
||||
ipt.y = y + (h - isz.height) / 2
|
||||
elif flag & wxALIGN_BOTTOM:
|
||||
ipt.y = y + (h - isz.height)
|
||||
|
||||
item.SetDimension(ipt, isz)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
class wxFlexGridSizer(wxGridSizer):
|
||||
def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
|
||||
wxGridSizer.__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 wxSize(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 = wxSize(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
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.grids
|
||||
|
||||
__doc__ = wx.lib.grids.__doc__
|
||||
|
||||
wxFlexGridSizer = wx.lib.grids.wxFlexGridSizer
|
||||
wxGridSizer = wx.lib.grids.wxGridSizer
|
||||
|
||||
@@ -1,315 +1,14 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: BrowseImage.py
|
||||
# Purpose: Display and Select Image Files
|
||||
#
|
||||
# Author: Lorne White
|
||||
#
|
||||
# Version: 1.0
|
||||
# Date: January 29, 2002
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
# 1.0 Release
|
||||
# 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 wx.lib.imagebrowser
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
__doc__ = wx.lib.imagebrowser.__doc__
|
||||
|
||||
import os, sys
|
||||
from wxPython.wx import *
|
||||
dir_path = os.getcwd()
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
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()
|
||||
if ext == 'bmp':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_BMP)
|
||||
elif ext == 'gif':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_GIF)
|
||||
elif ext == 'png':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_PNG)
|
||||
elif ext == 'jpg':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_JPEG)
|
||||
elif ext == 'pcx':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_PCX)
|
||||
elif ext == 'tif':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_TIF)
|
||||
elif ext == 'pnm':
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_PNM)
|
||||
else:
|
||||
image = wxImage(file_nm, wxBITMAP_TYPE_ANY)
|
||||
|
||||
return image
|
||||
|
||||
def GetSize(file_nm): # for scaling image values
|
||||
image = ConvertBMP(file_nm)
|
||||
bmp = image.ConvertToBitmap()
|
||||
size = bmp.GetWidth(), bmp.GetHeight()
|
||||
return size
|
||||
|
||||
class ImageView(wxWindow):
|
||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, size=wxDefaultSize):
|
||||
wxWindow.__init__(self, parent, id, pos, size)
|
||||
self.win = parent
|
||||
self.image = None
|
||||
self.back_color = 'WHITE'
|
||||
self.border_color = 'BLACK'
|
||||
|
||||
self.image_sizex = size.width
|
||||
self.image_sizey = size.height
|
||||
self.image_posx = pos.x
|
||||
self.image_posy = pos.y
|
||||
EVT_PAINT(self, self.OnPaint)
|
||||
|
||||
wxInitAllImageHandlers()
|
||||
|
||||
def OnPaint(self, event):
|
||||
dc = wxPaintDC(self)
|
||||
self.DrawImage(dc)
|
||||
|
||||
def DrawImage(self, dc):
|
||||
dc.BeginDrawing()
|
||||
self.DrawImage(dc)
|
||||
dc.EndDrawing()
|
||||
|
||||
def SetValue(self, file_nm): # display the selected file in the panel
|
||||
image = ConvertBMP(file_nm)
|
||||
self.image = image
|
||||
self.Refresh()
|
||||
|
||||
def DrawBorder(self, dc):
|
||||
brush = wxBrush(wxNamedColour(self.back_color), wxSOLID)
|
||||
dc.SetBrush(brush)
|
||||
dc.SetPen(wxPen(wxNamedColour(self.border_color), 1))
|
||||
dc.DrawRectangle(0, 0, self.image_sizex, self.image_sizey)
|
||||
|
||||
def DrawImage(self, dc):
|
||||
try:
|
||||
image = self.image
|
||||
except:
|
||||
return
|
||||
|
||||
self.DrawBorder(dc)
|
||||
if image is None:
|
||||
return
|
||||
|
||||
bmp = image.ConvertToBitmap()
|
||||
|
||||
iwidth = bmp.GetWidth() # dimensions of image file
|
||||
iheight = bmp.GetHeight()
|
||||
|
||||
diffx = (self.image_sizex - iwidth)/2 # center calc
|
||||
if iwidth >= self.image_sizex -10: # if image width fits in window adjust
|
||||
diffx = 5
|
||||
iwidth = self.image_sizex - 10
|
||||
|
||||
diffy = (self.image_sizey - iheight)/2 # center calc
|
||||
if iheight >= self.image_sizey - 10: # if image height fits in window adjust
|
||||
diffy = 5
|
||||
iheight = self.image_sizey - 10
|
||||
|
||||
image.Rescale(iwidth, iheight) # rescale to fit the window
|
||||
image.ConvertToBitmap()
|
||||
bmp = image.ConvertToBitmap()
|
||||
dc.DrawBitmap(bmp, diffx, diffy) # draw the image to window
|
||||
|
||||
|
||||
class ImageDialog(wxDialog):
|
||||
def __init__(self, parent, set_dir = None):
|
||||
wxDialog.__init__(self, parent, -1, "Image Browser", wxPyDefaultPosition, wxSize(400, 400))
|
||||
|
||||
self.x_pos = 30 # initial display positions
|
||||
self.y_pos = 20
|
||||
self.delta = 20
|
||||
|
||||
size = wxSize(80, 25)
|
||||
|
||||
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
|
||||
|
||||
self.dir_x = self.x_pos
|
||||
self.dir_y = self.y_pos
|
||||
self.DisplayDir() # display the directory value
|
||||
|
||||
self.y_pos = self.y_pos + self.delta
|
||||
|
||||
mID = wxNewId()
|
||||
wxButton(self, mID, ' Set Directory ', wxPoint(self.x_pos, self.y_pos), size).SetDefault()
|
||||
EVT_BUTTON(self, mID, self.SetDirect)
|
||||
|
||||
self.type_posy = self.y_pos # save the y position for the image type combo
|
||||
|
||||
self.fl_ext = '*.bmp' # initial setting for file filtering
|
||||
self.GetFiles() # get the file list
|
||||
|
||||
self.y_pos = self.y_pos + self.delta + 10
|
||||
|
||||
self.list_height = 150
|
||||
|
||||
# List of Labels
|
||||
mID = wxNewId()
|
||||
self.tb = tb = wxListBox(self, mID, wxPoint(self.x_pos, self.y_pos), wxSize(160, self.list_height), self.fl_list, wxLB_SINGLE)
|
||||
EVT_LISTBOX(self, mID, self.OnListClick)
|
||||
EVT_LISTBOX_DCLICK(self, mID, self.OnListDClick)
|
||||
|
||||
width, height = self.tb.GetSizeTuple()
|
||||
image_posx = self.x_pos + width + 20 # positions for setting the image window
|
||||
image_posy = self.y_pos
|
||||
image_sizex = 150
|
||||
image_sizey = self.list_height
|
||||
|
||||
self.fl_types = ["All Images", "Bmp", "Gif", "Png", "Jpg", "Ico", "Pnm", "Pcx", "Tif", "All Files"]
|
||||
self.fl_ext_types = { "All Images": "All", "Bmp": "*.bmp", "Gif": "*.gif", "Png": "*.png", "Jpg": "*.jpg",
|
||||
"Ico": "*.ico", "Pnm": "*.pnm", "Pcx": "*.pcx", "Tif": "*.tif", "All Files": "*.*" }
|
||||
|
||||
self.set_type = self.fl_types[0] # initial file filter setting
|
||||
self.fl_ext = self.fl_ext_types[self.set_type]
|
||||
|
||||
mID = wxNewId()
|
||||
self.sel_type = wxComboBox(self, mID, self.set_type, wxPoint(image_posx , self.type_posy), wxSize(150, -1), self.fl_types, wxCB_DROPDOWN)
|
||||
EVT_COMBOBOX(self, mID, self.OnSetType)
|
||||
|
||||
self.image_view = ImageView(self, pos=wxPoint(image_posx, image_posy), size=wxSize(image_sizex, image_sizey))
|
||||
|
||||
self.y_pos = self.y_pos + height + 20
|
||||
|
||||
mID = wxNewId()
|
||||
wxButton(self, mID, ' Select ', wxPoint(100, self.y_pos), size).SetDefault()
|
||||
EVT_BUTTON(self, mID, self.OnOk)
|
||||
|
||||
wxButton(self, wxID_CANCEL, 'Cancel', wxPoint(250, self.y_pos), size)
|
||||
|
||||
self.y_pos = self.y_pos + self.delta
|
||||
fsize = wxSize(400, self.y_pos + 50) # resize dialog for final vertical position
|
||||
self.SetSize(fsize)
|
||||
|
||||
self.ResetFiles()
|
||||
|
||||
def GetFiles(self): # get the file list using directory and extension values
|
||||
if self.fl_ext == "All":
|
||||
all_files = []
|
||||
for ftypes in self.fl_types[1:-1]: # get list of all available image types
|
||||
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
|
||||
|
||||
def DisplayDir(self): # display the working directory
|
||||
wxStaticText(self, -1, self.set_dir, wxPoint(self.dir_x, self.dir_y), wxSize(250, -1))
|
||||
|
||||
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(0)
|
||||
|
||||
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)
|
||||
self.image_view.SetValue(file_val)
|
||||
|
||||
def SetDirect(self, event): # set the new directory
|
||||
dlg = wxDirDialog(self)
|
||||
dlg.SetPath(self.set_dir)
|
||||
if dlg.ShowModal() == wxID_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()
|
||||
self.tb.Set(self.fl_list)
|
||||
try:
|
||||
self.tb.SetSelection(0)
|
||||
self.SetListValue(0)
|
||||
except:
|
||||
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(wxID_CANCEL)
|
||||
|
||||
def OnOk(self, event):
|
||||
self.result = self.set_file
|
||||
self.EndModal(wxID_OK)
|
||||
|
||||
|
||||
def OnFileDlg(self):
|
||||
dlg = wxFileDialog(self, "Choose an Image File", ".", "", "Bmp (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg", wxOPEN)
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
path = dlg.GetPath()
|
||||
else:
|
||||
path = None
|
||||
dlg.Destroy()
|
||||
return path
|
||||
|
||||
class FindFiles:
|
||||
def __init__(self, parent, dir, mask):
|
||||
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)
|
||||
path = path.upper()
|
||||
value = i.upper()
|
||||
|
||||
if pattern.match(value) != None:
|
||||
filelist.append(i)
|
||||
|
||||
self.files = filelist
|
||||
|
||||
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:]
|
||||
ConvertBMP = wx.lib.imagebrowser.ConvertBMP
|
||||
FindFiles = wx.lib.imagebrowser.FindFiles
|
||||
GetSize = wx.lib.imagebrowser.GetSize
|
||||
ImageDialog = wx.lib.imagebrowser.ImageDialog
|
||||
ImageView = wx.lib.imagebrowser.ImageView
|
||||
OnFileDlg = wx.lib.imagebrowser.OnFileDlg
|
||||
|
||||
@@ -1,45 +1,10 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.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
|
||||
#----------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
from __future__ import nested_scopes
|
||||
import wx.lib.imageutils
|
||||
|
||||
__doc__ = wx.lib.imageutils.__doc__
|
||||
|
||||
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
|
||||
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)))
|
||||
|
||||
|
||||
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)
|
||||
grayOut = wx.lib.imageutils.grayOut
|
||||
makeGray = wx.lib.imageutils.makeGray
|
||||
|
||||
@@ -1,471 +1,11 @@
|
||||
"""
|
||||
infoframe.py
|
||||
Released under wxWindows license etc.
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
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...
|
||||
import wx.lib.infoframe
|
||||
|
||||
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 wxPython.lib.infoframe import *
|
||||
... # ... modify your wxApp as follows:
|
||||
class myApp(wxApp):
|
||||
outputWindowClass = wxPyInformationalMessagesFrame
|
||||
...
|
||||
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 = wxPyInformationalMessagesFrame\
|
||||
([options from progname (default ""),
|
||||
txt (default "informational
|
||||
messages"])
|
||||
#^^^^ early in the program
|
||||
...
|
||||
InformationalMessagesFrame([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.
|
||||
|
||||
"""
|
||||
|
||||
from wxPython.wx import *
|
||||
import sys, tempfile, os
|
||||
|
||||
class _MyStatusBar(wxStatusBar):
|
||||
def __init__(self, parent,callbacks=None,useopenbutton=0):
|
||||
wxStatusBar.__init__(self, parent, -1, style=wxTAB_TRAVERSAL)
|
||||
self.SetFieldsCount(3)
|
||||
|
||||
self.SetStatusText("",0)
|
||||
|
||||
ID = wxNewId()
|
||||
self.button1 = wxButton(self,ID,"Dismiss",
|
||||
style=wxTAB_TRAVERSAL)
|
||||
EVT_BUTTON(self,ID,self.OnButton1)
|
||||
|
||||
ID = wxNewId()
|
||||
if not useopenbutton:
|
||||
self.button2 = wxButton(self,ID,"Close File",
|
||||
style=wxTAB_TRAVERSAL)
|
||||
else:
|
||||
self.button2 = wxButton(self,ID,"Open New File",
|
||||
style=wxTAB_TRAVERSAL)
|
||||
EVT_BUTTON(self,ID,self.OnButton2)
|
||||
self.useopenbutton = useopenbutton
|
||||
self.callbacks = callbacks
|
||||
|
||||
# figure out how tall to make the status bar
|
||||
dc = wxClientDC(self)
|
||||
dc.SetFont(self.GetFont())
|
||||
(w,h) = dc.GetTextExtent('X')
|
||||
h = int(h * 1.8)
|
||||
self.SetSize(wxSize(100, h))
|
||||
self.OnSize("dummy")
|
||||
EVT_SIZE(self,self.OnSize)
|
||||
|
||||
# reposition things...
|
||||
def OnSize(self, event):
|
||||
self.CalculateSizes()
|
||||
rect = self.GetFieldRect(1)
|
||||
self.button1.SetPosition(wxPoint(rect.x+5, rect.y+2))
|
||||
self.button1.SetSize(wxSize(rect.width-10, rect.height-4))
|
||||
rect = self.GetFieldRect(2)
|
||||
self.button2.SetPosition(wxPoint(rect.x+5, rect.y+2))
|
||||
self.button2.SetSize(wxSize(rect.width-10, rect.height-4))
|
||||
|
||||
# widths........
|
||||
def CalculateSizes(self):
|
||||
dc = wxClientDC(self.button1)
|
||||
dc.SetFont(self.button1.GetFont())
|
||||
(w1,h) = dc.GetTextExtent(self.button1.GetLabel())
|
||||
|
||||
dc = wxClientDC(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 wxPyInformationalMessagesFrame:
|
||||
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 wxThread_IsMain():
|
||||
# Aquire the GUI mutex before making GUI calls. Mutex is released
|
||||
# when locker is deleted at the end of this function.
|
||||
locker = wxMutexGuiLocker()
|
||||
|
||||
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 = wxFrame(self.parent, -1, self.title, size=(450, 300),
|
||||
style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
self.text = wxTextCtrl(self.frame, -1, "",
|
||||
style = wxTE_MULTILINE|wxTE_READONLY|wxTE_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)
|
||||
EVT_CLOSE(self.frame, 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 = wxFileDialog(self.frame,
|
||||
"Choose a new log file", self.dir,"","*",
|
||||
wxSAVE | wxHIDE_READONLY | wxOVERWRITE_PROMPT)
|
||||
if dlg.ShowModal() == wxID_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()
|
||||
wxYield()
|
||||
|
||||
|
||||
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_wxPyInformationalMessagesFrame:
|
||||
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
|
||||
__doc__ = wx.lib.infoframe.__doc__
|
||||
|
||||
Dummy_wxPyInformationalMessagesFrame = wx.lib.infoframe.Dummy_wxPyInformationalMessagesFrame
|
||||
_MyStatusBar = wx.lib.infoframe._MyStatusBar
|
||||
wxPyInformationalMessagesFrame = wx.lib.infoframe.wxPyInformationalMessagesFrame
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,263 +1,9 @@
|
||||
from wxPython.wx import wxLayoutConstraints,\
|
||||
wxTop, wxLeft, wxBottom, wxRight, \
|
||||
wxHeight, wxWidth, wxCentreX, wxCentreY
|
||||
import re
|
||||
|
||||
class Layoutf(wxLayoutConstraints):
|
||||
"""
|
||||
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 = wxLayoutContraints()
|
||||
lc.top.SameAs(self, wxTop)
|
||||
lc.left.SameAs(self.panel, wxRight, 10)
|
||||
lc.right.Absolute(100)
|
||||
lc.height.PercentOf(self, wxHeight, 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>,
|
||||
wxHeight, 50) and t=b#1 ( lc.top.SameAs(<first obj>,
|
||||
wxBottom) )
|
||||
|
||||
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': 'wxBottom'
|
||||
'r': 'wxRight', 'h': 'wxHeight', 'w': 'wxWidth',
|
||||
'x': 'wxCentreX', 'y': 'wxCentreY'
|
||||
|
||||
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': 'wxTop', 'l': 'wxLeft', 'b': 'wxBottom',
|
||||
'r': 'wxRight', 'h': 'wxHeight', 'w': 'wxWidth',
|
||||
'x': 'wxCentreX', 'y': 'wxCentreY' }
|
||||
|
||||
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):
|
||||
wxLayoutConstraints.__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__':
|
||||
from wxPython.wx import *
|
||||
|
||||
class TestLayoutf(wxFrame):
|
||||
def __init__(self, parent):
|
||||
wxFrame.__init__(self, parent, -1, 'Test Layout Constraints',
|
||||
wxPyDefaultPosition, wxSize(500, 300))
|
||||
EVT_CLOSE(self, self.OnCloseWindow)
|
||||
|
||||
self.SetAutoLayout(True)
|
||||
EVT_BUTTON(self, 100, self.OnButton)
|
||||
EVT_BUTTON(self, 101, self.OnAbout)
|
||||
|
||||
self.panelA = wxWindow(self, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
|
||||
self.panelA.SetBackgroundColour(wxBLUE)
|
||||
self.panelA.SetConstraints(Layoutf('t=t10#1;l=l10#1;b=b10#1;r%r50#1',(self,)))
|
||||
|
||||
self.panelB = wxWindow(self, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
|
||||
self.panelB.SetBackgroundColour(wxRED)
|
||||
self.panelB.SetConstraints(Layoutf('t=t10#1;r=r10#1;b%b30#1;l>10#2', (self,self.panelA)))
|
||||
|
||||
self.panelC = wxWindow(self, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
|
||||
self.panelC.SetBackgroundColour(wxWHITE)
|
||||
self.panelC.SetConstraints(Layoutf('t_10#3;r=r10#1;b=b10#1;l>10#2', (self,self.panelA,self.panelB)))
|
||||
|
||||
b = wxButton(self.panelA, 101, ' About: ')
|
||||
b.SetConstraints(Layoutf('X=X#1;Y=Y#1;h*;w%w50#1', (self.panelA,)))
|
||||
|
||||
b = wxButton(self.panelB, 100, ' Panel B ')
|
||||
b.SetConstraints(Layoutf('t=t2#1;r=r4#1;h*;w*', (self.panelB,)))
|
||||
|
||||
self.panelD = wxWindow(self.panelC, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
|
||||
self.panelD.SetBackgroundColour(wxGREEN)
|
||||
self.panelD.SetConstraints(Layoutf('b%h50#1;r%w50#1;h=h#2;w=w#2', (self.panelC, b)))
|
||||
|
||||
b = wxButton(self.panelC, 100, ' Panel C ')
|
||||
b.SetConstraints(Layoutf('t_#1;l>#1;h*;w*', (self.panelD,)))
|
||||
|
||||
wxStaticText(self.panelD, -1, "Panel D", wxPoint(4, 4)).SetBackgroundColour(wxGREEN)
|
||||
|
||||
def OnButton(self, event):
|
||||
self.Close(True)
|
||||
|
||||
def OnAbout(self, event):
|
||||
try:
|
||||
from dialogs import wxScrolledMessageDialog
|
||||
msg = wxScrolledMessageDialog(self, Layoutf.__doc__, "about")
|
||||
msg.ShowModal()
|
||||
except:
|
||||
print msg
|
||||
|
||||
def OnCloseWindow(self, event):
|
||||
self.Destroy()
|
||||
|
||||
class TestApp(wxApp):
|
||||
def OnInit(self):
|
||||
frame = TestLayoutf(NULL)
|
||||
frame.Show(1)
|
||||
self.SetTopWindow(frame)
|
||||
return 1
|
||||
|
||||
app = TestApp(0)
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
import wx.lib.layoutf
|
||||
|
||||
__doc__ = wx.lib.layoutf.__doc__
|
||||
|
||||
Layoutf = wx.lib.layoutf.Layoutf
|
||||
|
||||
@@ -1,101 +1,10 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: wxPython.lib.maskedctrl.py
|
||||
# Author: Will Sadkin
|
||||
# Created: 09/24/2003
|
||||
# Copyright: (c) 2003 by Will Sadkin
|
||||
# RCS-ID: $Id$
|
||||
# License: wxWindows license
|
||||
#----------------------------------------------------------------------------
|
||||
## This file imports items from the wx package into the wxPython package for
|
||||
## backwards compatibility. Some names will also have a 'wx' added on if
|
||||
## that is how they used to be named in the old wxPython package.
|
||||
|
||||
"""<html><body>
|
||||
<P>
|
||||
<B>wxMaskedCtrl</B> is actually a factory function for several types of
|
||||
masked edit controls:
|
||||
<P>
|
||||
<UL>
|
||||
<LI><b>wxMaskedTextCtrl</b> - standard masked edit text box</LI>
|
||||
<LI><b>wxMaskedComboBox</b> - adds combobox capabilities</LI>
|
||||
<LI><b>wxIpAddrCtrl</b> - adds logical input semantics for IP address entry</LI>
|
||||
<LI><b>wxTimeCtrl</b> - special subclass handling lots of time formats as values</LI>
|
||||
<LI><b>wxMaskedNumCtrl</b> - special subclass handling numeric values</LI>
|
||||
</UL>
|
||||
<P>
|
||||
<B>wxMaskedCtrl</B> works by looking for a special <b><i>controlType</i></b>
|
||||
parameter in the variable arguments of the control, to determine
|
||||
what kind of instance to return.
|
||||
controlType can be one of:
|
||||
<PRE><FONT SIZE=-1>
|
||||
controlTypes.MASKEDTEXT
|
||||
controlTypes.MASKEDCOMBO
|
||||
controlTypes.IPADDR
|
||||
controlTypes.TIME
|
||||
controlTypes.NUMBER
|
||||
</FONT></PRE>
|
||||
These constants are also available individually, ie, you can
|
||||
use either of the following:
|
||||
<PRE><FONT SIZE=-1>
|
||||
from wxPython.wx.lib.maskedctrl import wxMaskedCtrl, MASKEDCOMBO, MASKEDTEXT, NUMBER
|
||||
from wxPython.wx.lib.maskedctrl import wxMaskedCtrl, controlTypes
|
||||
</FONT></PRE>
|
||||
If not specified as a keyword argument, the default controlType is
|
||||
controlTypes.MASKEDTEXT.
|
||||
<P>
|
||||
Each of the above classes has its own unique arguments, but wxMaskedCtrl
|
||||
provides a single "unified" interface for masked controls. wxMaskedTextCtrl,
|
||||
wxMaskedComboBox and wxIpAddrCtrl are all documented below; the others have
|
||||
their own demo pages and interface descriptions.
|
||||
</body></html>
|
||||
"""
|
||||
|
||||
from wxPython.lib.maskededit import wxMaskedTextCtrl, wxMaskedComboBox, wxIpAddrCtrl
|
||||
from wxPython.lib.maskednumctrl import wxMaskedNumCtrl
|
||||
from wxPython.lib.timectrl import wxTimeCtrl
|
||||
|
||||
|
||||
# "type" enumeration for class instance factory function
|
||||
MASKEDTEXT = 0
|
||||
MASKEDCOMBO = 1
|
||||
IPADDR = 2
|
||||
TIME = 3
|
||||
NUMBER = 4
|
||||
|
||||
# for ease of import
|
||||
class controlTypes:
|
||||
MASKEDTEXT = MASKEDTEXT
|
||||
MASKEDCOMBO = MASKEDCOMBO
|
||||
IPADDR = IPADDR
|
||||
TIME = TIME
|
||||
NUMBER = NUMBER
|
||||
|
||||
|
||||
def wxMaskedCtrl( *args, **kwargs):
|
||||
"""
|
||||
Actually a factory function providing a unifying
|
||||
interface for generating masked controls.
|
||||
"""
|
||||
if not kwargs.has_key('controlType'):
|
||||
controlType = MASKEDTEXT
|
||||
else:
|
||||
controlType = kwargs['controlType']
|
||||
del kwargs['controlType']
|
||||
|
||||
if controlType == MASKEDTEXT:
|
||||
return wxMaskedTextCtrl(*args, **kwargs)
|
||||
|
||||
elif controlType == MASKEDCOMBO:
|
||||
return wxMaskedComboBox(*args, **kwargs)
|
||||
|
||||
elif controlType == IPADDR:
|
||||
return wxIpAddrCtrl(*args, **kwargs)
|
||||
|
||||
elif controlType == TIME:
|
||||
return wxTimeCtrl(*args, **kwargs)
|
||||
|
||||
elif controlType == NUMBER:
|
||||
return wxMaskedNumCtrl(*args, **kwargs)
|
||||
|
||||
else:
|
||||
raise AttributeError(
|
||||
"invalid controlType specified: %s" % repr(controlType))
|
||||
import wx.lib.maskedctrl
|
||||
|
||||
__doc__ = wx.lib.maskedctrl.__doc__
|
||||
|
||||
controlTypes = wx.lib.maskedctrl.controlTypes
|
||||
wxMaskedCtrl = wx.lib.maskedctrl.wxMaskedCtrl
|
||||
|
||||
+16
-7365
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user