# Programmer: Daniel Pozmanter
# E-mail: drpython@bluebottle.com
# Note: You must reply to the verification e-mail to get through.
#
# Copyright 2003-2005 Daniel Pozmanter
#
# Distributed under the terms of the GPL (GNU Public License)
#
# DrPython is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Icons taken from "Noia Kde 100" by Carles Carbonell Bernado from the KDE-LOOK site (some edited a bit).
# An excellent artist.
#Source Browser
import wx
import drScrolledMessageDialog
from drProperty import *
import wx.stc
import re
recolour = re.compile('#\w+')
def GetCount(line, compchar):
l = len(line)
x = 0
y = 0
while(x < l):
if (line[x] == compchar):
y = y + 1
elif (not line[x].isspace()):
x = l
x = x + 1
return y
class drTree(wx.TreeCtrl):
def __init__(self, parent, id, point, size, style, ancestor):
wx.TreeCtrl.__init__(self, parent, id, point, size, style)
self.grandparent = ancestor
self.parent = parent
style = self.grandparent.prefs.sourcebrowserstyle
yarrr = convertStyleStringToWXFontArray(style)
imagesize = (16,16)
self.imagelist = wx.ImageList(imagesize[0], imagesize[1])
self.images = [wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/class.png", wx.BITMAP_TYPE_PNG)),
wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/def.png", wx.BITMAP_TYPE_PNG)),
wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/import.png", wx.BITMAP_TYPE_PNG)),
wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/transparent.png", wx.BITMAP_TYPE_PNG))]
map(self.imagelist.Add, self.images)
self.AssignImageList(self.imagelist)
w = wx.Font(yarrr[1], wx.NORMAL, wx.NORMAL, wx.NORMAL, yarrr[2])
w.SetFaceName(yarrr[0])
if (yarrr[3]):
w.SetWeight(wx.BOLD)
else:
w.SetWeight(wx.NORMAL)
if (yarrr[4]):
w.SetStyle(wx.ITALIC)
else:
w.SetStyle(wx.NORMAL)
self.SetFont(w)
f = convertColorPropertyToColorArray(getStyleProperty("fore", style))
b = convertColorPropertyToColorArray(getStyleProperty("back", style))
self.TextColor = wx.Colour(f[0], f[1], f[2])
self.SetForegroundColour(self.TextColor)
self.SetBackgroundColour(wx.Colour(b[0], b[1], b[2]))
self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated, id=id)
self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnItemActivated, id=id)
def OnCompareItems(self, item1, item2):
#Overriding Base, Return -1 for <, 0 for ==, +1 for >
t1 = self.GetItemText(item1).lower()
t2 = self.GetItemText(item2).lower()
x = 0
l = len(t1)
if (l > len(t2)):
l = len(t2)
while(x < l):
if (t1[x] < t2[x]):
return -1
elif (t1[x] > t2[x]):
return 1
x = x + 1
if (l == len(t2)):
return -1
return 0
def OnItemActivated(self, event):
sel = self.GetSelection()
if (not sel.IsOk()):
return
t = self.GetItemText(sel)
lparen = t.find('(')
if lparen > -1:
length = len(t[:lparen])
else:
length = len(t)
try:
i = self.parent.ItemsIndex.index(sel)
pos = self.parent.ItemsPos[i]
line = self.grandparent.txtDocument.LineFromPosition(pos)
if (self.grandparent.prefs.docfolding):
#Make sure the line is visible.
self.grandparent.txtDocument.EnsureVisible(line)
self.grandparent.txtDocument.ScrollToLine(line)
self.grandparent.txtDocument.GotoLine(line)
self.grandparent.txtDocument.GotoPos(pos)
self.grandparent.Raise()
self.grandparent.SetFocus()
if (self.grandparent.prefs.sourcebrowsercloseonactivate):
self.parent.OnbtnClose(event)
else:
self.grandparent.txtDocument.SetFocus()
except:
drScrolledMessageDialog.ShowMessage(self.parent, 'Error Activating Item', 'Source Browser Error')
class drSourceBrowserPanel(wx.Panel):
def __init__(self, parent, id, Position, Index):
wx.Panel.__init__(self, parent, id)
self.theSizer = wx.BoxSizer(wx.VERTICAL)
self.mixed = 0
self.renext = re.compile(r'^[ \t]*[^#^\s]', re.M)
self.reinspect = re.compile(r'(^[ \t]*?class\s.*[(:])|(^[ \t]*?def\s.*[(:])|(^[ \t]*?import\s.*$)|(^[ \t]*?from\s.*$)|(^\s*#---.+)', re.MULTILINE)
self.panelparent = parent.GetGrandParent().GetParent()
self.parent = parent.GetGrandParent().GetGrandParent()
self.classtree = drTree(self, -1, wx.Point(0, 0), wx.Size(400, 200), wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT, self.parent)
self.btnClose = wx.Button(self, 101, "&Close")
self.btnRefresh = wx.Button(self, 102, "&Refresh")
self.theSizer.Add(self.classtree, 9, wx.EXPAND)
self.bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.bSizer.Add(self.btnRefresh, 0, wx.SHAPED | wx.ALIGN_LEFT)
self.bSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_RIGHT)
self.theSizer.Add(self.bSizer, 0, wx.EXPAND)
self.Position = Position
self.Index = Index
self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101)
self.Bind(wx.EVT_BUTTON, self.OnbtnRefresh, id=102)
self.parent.PBind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh, None)
self.eol = self.parent.txtDocument.GetEndOfLineCharacter()
if not self.Browse():
self.mixed = 1
msg = 'This document is mixed. It uses tabs and spaces for indentation.\nDrPython may not be able to correctly display the class browser. Please use "Edit:Whitespace:Clean Up Indentation" to fix this.'
drScrolledMessageDialog.ShowMessage(self, msg, "Check Indentation Results")
self.SetAutoLayout(True)
self.SetSizer(self.theSizer)
def Browse(self):
#Submitted Patch: Christian Daven
self.classtree.Freeze()
#/Submitted Patch: Christian Daven
self.classtree.DeleteAllItems()
self.root = self.classtree.AddRoot("")
self.ItemsIndex = []
self.ItemsPos = []
labelQueue = []
self.targetText = self.parent.txtDocument.GetText()
if self.mixed:
return 1
RootArray = [self.root]
Roots = [self.root]
currentRoot = 0
Indents = [0]
currentIndent = 0
eol = self.parent.txtDocument.GetEndOfLineCharacter()
#What is this document using?
result = self.parent.txtDocument.CheckIndentation()
wasnotmixed = 1
if result == 0:
wasnotmixed = 0
if self.parent.prefs.docusetabs[self.parent.txtDocument.filetype]:
result = 1
else:
result = -1
if (result == 1):
compchar = '\t'
dec = 1
else:
compchar = ' '
dec = self.parent.prefs.doctabwidth[0]
#Handle Triple Quoted Strings:
self.targetText = self.RemoveTripleQuotedString(self.targetText)
matcher = self.reinspect.finditer(self.targetText)
#Get On With It!
try:
match = matcher.next()
except:
match = None
while (match is not None):
matchedtext = match.group().strip()
if matchedtext[0] == '#':
nextmatch = self.renext.search(self.targetText[match.end():])
indent = 0
if nextmatch is not None:
indent = GetCount(nextmatch.group(), compchar)
cR = currentRoot
cI = currentIndent
while (indent < Indents[cI]):
cR = cR - 1
cI = cI - 1
i = matchedtext[4:].find('---')
if i > -1:
a = matchedtext[4:i+4]
else:
a = matchedtext[4:]
m = match.group().find('#')
currentitem = self.classtree.AppendItem(Roots[cI], a)
self.ItemsIndex.append(currentitem)
self.ItemsPos.append(match.start() + m)
colours = recolour.findall(matchedtext)
if len(colours) > 1:
try:
self.classtree.SetItemTextColour(currentitem, convertColorPropertyToColorArray(colours[0]))
self.classtree.SetItemBackgroundColour(currentitem, convertColorPropertyToColorArray(colours[1]))
except Exception, e:
print 'Error Setting Label Colour:', e
self.classtree.SetItemImage(currentitem, 3, wx.TreeItemIcon_Normal)
self.classtree.SetItemImage(currentitem, 3, wx.TreeItemIcon_Expanded)
else:
indent = GetCount(match.group(), compchar)
while (indent < Indents[currentIndent]):
Roots.pop()
currentRoot = currentRoot - 1
Indents.pop()
currentIndent = currentIndent - 1
Indents.append(indent + dec)
currentIndent = currentIndent + 1
currentitem = self.classtree.AppendItem(Roots[currentRoot], matchedtext)
Roots.append(currentitem)
#Submitted bugfix, Franz Steinhausler
self.classtree.SetPyData(Roots[-1], None)
currentRoot = currentRoot + 1
RootArray.append(Roots[currentRoot])
self.ItemsIndex.append(Roots[currentRoot])
self.ItemsPos.append(match.start())
if (matchedtext[0] == 'c'):
try:
fg, bg = convertStyleToColorArray(self.parent.prefs.PythonStyleDictionary[5])
self.classtree.SetItemTextColour(Roots[currentRoot], fg)
self.classtree.SetItemBackgroundColour(Roots[currentRoot], bg)
except Exception, e:
print 'Error Setting Class Colour:', e
self.classtree.SetItemImage(Roots[currentRoot], 0, wx.TreeItemIcon_Normal)
self.classtree.SetItemImage(Roots[currentRoot], 0, wx.TreeItemIcon_Expanded)
elif (matchedtext[0] == 'd'):
try:
fg, bg = convertStyleToColorArray(self.parent.prefs.PythonStyleDictionary[8])
self.classtree.SetItemTextColour(Roots[currentRoot], fg)
self.classtree.SetItemBackgroundColour(Roots[currentRoot], bg)
except Exception, e:
print 'Error Setting Def Colour:', e
self.classtree.SetItemImage(Roots[currentRoot], 1, wx.TreeItemIcon_Normal)
self.classtree.SetItemImage(Roots[currentRoot], 1, wx.TreeItemIcon_Expanded)
else:
self.classtree.SetItemImage(Roots[currentRoot], 2, wx.TreeItemIcon_Normal)
self.classtree.SetItemImage(Roots[currentRoot], 2, wx.TreeItemIcon_Expanded)
try:
match = matcher.next()
except:
match = None
if (self.parent.prefs.sourcebrowserissorted):
self.classtree.SortChildren(self.root)
x = 0
l = len(RootArray)
while (x < l):
self.classtree.SortChildren(RootArray[x])
x = x + 1
#Submitted Patch: Christian Daven
self.classtree.Thaw()
#/Submitted Patch: Christian Daven
return wasnotmixed
def OnbtnClose(self, event):
self.parent.PUnbind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh)
self.parent.SourceBrowser = None
self.panelparent.ClosePanel(self.Position, self.Index)
def OnbtnRefresh(self, event):
self.mixed = 0
if not self.Browse():
self.mixed = 1
msg = 'This document is mixed. It uses tabs and spaces for indentation.\nDrPython may not be able to correctly display the class browser. Please use "Edit:Whitespace:Clean Up Indentation" to fix this.'
drScrolledMessageDialog.ShowMessage(self, msg, "Check Indentation Results")
if event is not None:
event.Skip()
def RemoveTripleQuotedString(self, text):
text = self.removeStringTripleQuotedWith(text, "'''")
text = self.removeStringTripleQuotedWith(text, '"""')
return text
def removeStringTripleQuotedWith(self, text, target):
start = text.find(target)
while start > -1:
end = text[start+3:].find(target)
if end == -1:
text = text[:start]
else:
end = start + 3 + end
text = text[:start] + "".zfill((end - start) + 3) + text[end+3:]
start = text.find(target)
return text
syntax highlighted by Code2HTML, v. 0.9.1