TestWin.py :  » GUI » wxPython » wxPython-src-2.8.11.0 » wxPython » wx » tools » XRCed » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » wxPython 
wxPython » wxPython src 2.8.11.0 » wxPython » wx » tools » XRCed » TestWin.py
# Name:         view.py
# Purpose:      TestWindow and related classes
# Author:       Roman Rolinsky <rolinsky@femagsoft.com>
# Created:      13.07.2007
# RCS-ID:       $Id: view.py 47356 2007-07-12 01:00:57Z ROL $

from globals import *
import wx
import view
from component import Manager

def getAllChildren(w):
    '''Get all children recursively.'''
    children = []
    for ch in w.GetChildren():
        children.append(ch)
        children.extend(getAllChildren(ch))
    return children

class TestWindow:
    '''Test window manager showing currently edited subtree.'''
    def __init__(self):
        self.Init()

    def Init(self):
        self.hl = self.hlDT = None      # highlight objects (Rect)
        self.frame = self.object = None # currenly shown frame and related object
        self.item = None
        self.pos = wx.DefaultPosition
        self.size = wx.DefaultSize        
        self.isDirty = False            # if refresh neeeded
        self.trash = []                 # trash to be destroyed later

    def SetView(self, frame, object, item):
        TRACE('SetView %s %s', frame, object)
        restoreSize = False
        if self.object:
            # Old window must be destroyed if new uses different frame
            # or is itself a toplevel window
            if not frame or frame and not self.frame:
                # Remember old item
                if item == self.item:
                    restoreSize = True
                TRACE('Closing old frame, restoreSize=%d', restoreSize)
                self.GetFrame().Close()
            elif self.frame:
                # Destroy old object but re-use frame
                self.object.Destroy()
        self.frame = frame
        self.object = object
        self.isDirty = False
        object.SetDropTarget(DropTarget(object))
        if wx.Platform == '__WXMAC__':
            for ch in getAllChildren(object):
                ch.SetDropTarget(DropTarget(ch))
        if wx.Platform == '__WXMSW__':
            object.Bind(wx.EVT_PAINT, self.OnPaint)
        if self.pos != wx.DefaultPosition:
            self.GetFrame().SetPosition(self.pos)
        if restoreSize:   # keep same size in refreshing
            TRACE('restoring size %s', self.size)
            self.GetFrame().SetSize(self.size)
        self.item = item
        self.hl = self.hlDT = None
        g.Listener.InstallTestWinEvents()

    def OnPaint(self, evt):
        # This is a completely crazy way to force wxMSW to refresh
        # highlight _after_ window is painted
        dc = wx.PaintDC(self.object)
        dc.Destroy()
        self.object.Bind(wx.EVT_IDLE, self.OnIdle)

    def OnIdle(self, evt):
        self.object.Unbind(wx.EVT_IDLE)
        if self.hl: self.hl.Refresh()
        if self.hlDT: self.hlDT.Refresh()
                
    def GetFrame(self):
        if self.frame: return self.frame
        else: return self.object

    def Show(self, show=True):
        TRACE('TestWindow.Show')
        self.GetFrame().Show(show)

        # re-raise the main window so the test window doesn't steal
        # the activation from it.
        if g.lastActiveFrame:
            g.lastActiveFrame.Raise()   
        
    def IsShown(self):
        return self.object is not None and self.object.IsShown()

    def IsDirty(self):
        '''If test window must be refreshed.'''
        return self.IsShown() and self.isDirty

    def EmptyTrash(self):
        [l.Destroy() for l in self.trash]
        self.trash = []

    def Destroy(self):
        TRACE('Destroy test window')
        # Remember dimensions
        self.pos = self.GetFrame().GetPosition()
        self.size = self.GetFrame().GetSize()
        self.GetFrame().Destroy()
        self.frame = self.object = self.item = None
        self.hl = self.hlDT = None
        self.trash = []

    # Find the object for an item
    def FindObject(self, item):
        tree = view.tree
        if not item or item == tree.root:
            return None
        if item == self.item: return self.object
        # Traverse tree until we reach the root  or the test object
        items = [item]
        while 1:
            item = tree.GetItemParent(item)
            if item == tree.root: return None # item outside if the test subtree
            elif item == self.item: break
            else: items.append(item)
        # Now traverse back, searching children
        obj = self.object
        comp = Manager.getNodeComp(tree.GetPyData(self.item))
        while items and obj:
            if not (isinstance(obj, wx.Window) or isinstance(obj, wx.Sizer)):
                return None
            parentItem = item
            item = items.pop()
            index = tree.ItemIndex(item)
            obj = comp.getChildObject(tree.GetPyData(parentItem), obj, index)
            node = tree.GetPyData(item)
            comp = Manager.getNodeComp(node)
        return obj

    # Find tree item corresponding to testWin object
    def FindObjectItem(self, item, obj):
        # We simply perform depth-first traversal, sinse it's too much
        # hassle to deal with all sizer/window combinations
        w = self.FindObject(item)
        if w == obj or isinstance(w, wx.SizerItem) and w.GetWindow() == obj:
            return item
        if view.tree.ItemHasChildren(item):
            child = view.tree.GetFirstChild(item)[0]
            while child:
                found = self.FindObjectItem(child, obj)
                if found: return found
                child = view.tree.GetNextSibling(child)
        return None

    # Find the rectangle or rectangles corresponding to a tree item
    # in the test window (or return None)
    def FindObjectRect(self, item):
        tree = view.tree
        if not item or item == tree.root: return None
        if item == self.item:   # top-level
            comp = Manager.getNodeComp(tree.GetPyData(item))
            rects = comp.getRect(self.object)
            if rects:
                # Make rects relative to the object
                offset = wx.Point(-rects[0].GetLeft(),-rects[0].GetTop())
                [r.Offset(offset) for r in rects]
            return rects
        # Traverse tree until we reach the root  or the test object
        items = [item]
        while 1:
            item = tree.GetItemParent(item)
            if item == self.item: break
            elif item == tree.root: return None # item outside of the test subtree
            else: items.append(item)
        # Now traverse back from parents to children
        obj = self.object
        offset = wx.Point(0,0)
        rects = None
        comp = Manager.getNodeComp(tree.GetPyData(self.item))
        while items and obj:
            if not (isinstance(obj, wx.Window) or isinstance(obj, wx.Sizer)):
                return None
            parentItem = item
            if rects: parentRect = rects[0]
            parent = obj
            item = items.pop()
            index = tree.ItemIndex(item)
            obj = comp.getChildObject(tree.GetPyData(parentItem), parent, index)
            if isinstance(parent, wx.Notebook) and index != parent.GetSelection():
                parent.SetSelection(index)
            node = tree.GetPyData(item)
            comp = Manager.getNodeComp(node)
            rects = comp.getRect(obj)
            if not rects: return None
            r = rects[0]
            if isinstance(parent, wx.Sizer) and parentRect:
                sizerItem = parent.GetChildren()[index]
                flag = sizerItem.GetFlag()
                border = sizerItem.GetBorder()
                if border != 0:
                    x = (r.GetLeft() + r.GetRight()) / 2
                    if flag & wx.TOP:
                        rects.append(wx.Rect(x, r.GetTop() - border, 0, border))
                    if flag & wx.BOTTOM:
                        rects.append(wx.Rect(x, r.GetBottom() + 1, 0, border))
                    y = (r.GetTop() + r.GetBottom()) / 2
                    if flag & wx.LEFT:
                        rects.append(wx.Rect(r.GetLeft() - border, y, border, 0))
                    if flag & wx.RIGHT:
                        rects.append(wx.Rect(r.GetRight() + 1, y, border, 0))
            if isinstance(obj, wx.Notebook) and items:
                offset += obj.GetClientRect().GetTopLeft()
            elif isinstance(obj, wx.Window) and items:
                offset += r.GetTopLeft()
        [r.Offset(offset) for r in rects]
        return rects

    def Highlight(self, rect):
        if not self.hl:
            self.hl = Highlight(self.object, rect)
        else:
            self.hl.Move(rect)
            
    def HighlightDT(self, rect, item):
        if not self.hlDT:
            self.hlDT = Highlight(self.object, rect, wx.BLUE, False)
            self.hlDT.origColour = view.tree.GetItemTextColour(item)
        else:
            self.hlDT.Move(rect)
            view.tree.SetItemTextColour(self.hlDT.item, self.hlDT.origColour)
        view.tree.SetItemTextColour(item, view.tree.COLOUR_DT)            
        self.hlDT.item = item
            
    def RemoveHighlight(self):
        if self.hl is None: return
        self.hl.Destroy()
        self.EmptyTrash()
        self.hl = None
        
    def RemoveHighlightDT(self):
        if self.hlDT is None: return
        if self.hlDT.item:
            view.tree.SetItemTextColour(self.hlDT.item, self.hlDT.origColour)
        # Destroying is sensitive if done directly in DropTarget methods
        wx.CallAfter(self.hlDT.Destroy)
        self.hlDT = None
        view.frame.SetStatusText('')

            
################################################################################

# DragAndDrop

class DropTarget(wx.DropTarget):
    def __init__(self, win):
        self.win = win
        self.do = MyDataObject()
        wx.DropTarget.__init__(self, self.do)
        self.onHL = self.left = False

    # Find best object for dropping
    def WhereToDrop(self, x, y, d):
        # Find object by position
        if wx.Platform == '__WXMAC__': # on mac x,y relative to children
            scrPos = self.win.ClientToScreen((x,y))
        else:
            scrPos = view.testWin.object.ClientToScreen((x,y))
        obj = wx.FindWindowAtPoint(scrPos)
        if not obj:
            return wx.DragNone, ()
        if obj.GetId() == Highlight.ID_HL:
            self.onHL = True
            return d, ()
        item = view.testWin.FindObjectItem(view.testWin.item, obj)
        if not item:
            return wx.DragNone, ()
        # If window has a sizer use it as parent
        if obj.GetSizer():
            obj = obj.GetSizer()
            item = view.testWin.FindObjectItem(view.testWin.item, obj)
        return d, (obj,item)

    # Drop
    def OnData(self, x, y, d):
        view.testWin.RemoveHighlightDT()
        self.onHL = self.left = False
        self.GetData()
        id = int(self.do.GetDataHere())
        d,other = self.WhereToDrop(x, y, d)
        if d != wx.DragNone and other:
            obj,item = other
            g.Presenter.setData(item)
            comp = Manager.findById(id)
            mouseState = wx.GetMouseState()
            forceSibling = mouseState.ControlDown()
            forceInsert = mouseState.ShiftDown()
            g.Presenter.updateCreateState(forceSibling, forceInsert)
            if not g.Presenter.checkCompatibility(comp):
                return wx.DragNone
            item = g.Presenter.create(comp)
            node = view.tree.GetPyData(item)
            parentItem = view.tree.GetItemParent(item)
            parentNode = view.tree.GetPyData(parentItem)
            parentComp = Manager.getNodeComp(parentNode)
            # If pos if not set by default and parent is not a sizer, set pos to
            # drop coordinates
            if 'pos' in comp.attributes and not comp.getAttribute(node, 'pos') \
                   and parentComp.isContainer() and \
                   not parentComp.isSizer():
                # Calc relative coords
                rect = view.testWin.FindObjectRect(parentItem)
                x -= rect[0].x
                y -= rect[0].y
                comp.addAttribute(node, 'pos', '%d,%d' % (x, y))
                g.Presenter.setData(item)
            view.frame.SetStatusText('Object created')
        return d

    def OnDragOver(self, x, y, d):
        d,other = self.WhereToDrop(x, y, d)
        if d == wx.DragNone:
            view.frame.SetStatusText('Inappropriate drop target')
            view.testWin.RemoveHighlightDT()
        elif other:
            if self.left:
                view.testWin.RemoveHighlightDT()
                self.onHL = self.left = False
            obj,item = other
            hl = view.testWin.hlDT
            if not hl or hl.item != item:
                rect = view.testWin.FindObjectRect(item)
                if not rect: return wx.DragNone
                view.testWin.HighlightDT(rect, item)
                view.tree.EnsureVisible(item)
            view.frame.SetStatusText('Drop target: %s' % view.tree.GetItemText(item))
        return d

    def OnLeave(self):
        # Try to prevent flashing when pointer passes on highlight lines
        if self.onHL:
            view.testWin.RemoveHighlightDT()
            self.onHL = False
        else: self.left = True

################################################################################

class Highlight:
    '''
    Create a highlight rectangle by using multiple windows. rect is a
    single Rect or a list of Rects (for sizeritems).
    '''
    ID_HL = wx.NewId()
    def __init__(self, w, rect, colour=wx.Colour(222,0,0), more_lines=True):
        self.win = w
        self.colour = colour
        self.moreLines = more_lines
        rects = rect[1:]
        rect = rect[0]
        if rect.width == -1: rect.width = 0
        if rect.height == -1: rect.height = 0
        self.lines = [wx.Window(w, self.ID_HL, rect.GetTopLeft(), (rect.width, 2)),
                      wx.Window(w, self.ID_HL, rect.GetTopLeft(), (2, rect.height)),
                      wx.Window(w, self.ID_HL, (rect.x + rect.width - 2, rect.y), (2, rect.height)),
                      wx.Window(w, self.ID_HL, (rect.x, rect.y + rect.height - 2), (rect.width, 2))]
        for l in self.lines:
            l.SetBackgroundColour(colour)
            l.SetDropTarget(DropTarget(l))
        if wx.Platform == '__WXMSW__':
            [l.Bind(wx.EVT_PAINT, self.OnPaint) for l in self.lines]
        if more_lines: [self.AddSizerItem(r) for r in rects]

    # Repainting is not always done for these windows on Windows
    def OnPaint(self, evt):
        w = evt.GetEventObject()
        dc = wx.PaintDC(w)
        w.ClearBackground()
        dc.Destroy()
    def Destroy(self, i=0):
        '''Destroy highlight lines from some index.'''
        if wx.Platform == '__WXMAC__':
            [l.Hide() for l in self.lines[i:]]
            view.testWin.trash.extend(self.lines[i:])
        else:
            [l.Destroy() for l in self.lines[i:]]
        self.lines[i:] = []

    def Refresh(self):
        [l.Refresh() for l in self.lines]

    def Move(self, rect):
        rects = rect[1:]
        rect = rect[0]
        pos = rect.GetTopLeft()
        size = rect.GetSize()
        if size.width == -1: size.width = 0
        if size.height == -1: size.height = 0
        self.Destroy(4)
        self.lines[0].SetDimensions(pos.x, pos.y, size.width, 2)
        self.lines[1].SetDimensions(pos.x, pos.y, 2, size.height)
        self.lines[2].SetDimensions(pos.x + size.width - 2, pos.y, 2, size.height)
        self.lines[3].SetDimensions(pos.x, pos.y + size.height - 2, size.width, 2)
        [l.Raise() for l in self.lines]
        if self.moreLines: [self.AddSizerItem(r) for r in rects]

    def AddSizerItem(self, rect):
        w = self.win
        # 0 means a line from outer box to inner
        if rect.width == 0 or rect.height == 0:
            colour = wx.Colour(255,64,0)
            if rect.height == 0:
                line = wx.Window(w, -1, rect.GetTopLeft(), (rect.width, 1))
            else:
                line = wx.Window(w, -1, rect.GetTopLeft(), (1, rect.height))
            line.SetBackgroundColour(colour)
            self.lines.append(line)
            return
        colour = wx.Colour(255,0,0)
        lines = []
        lines.append(wx.Window(w, -1, rect.GetTopLeft(), (rect.width, 1)))
        lines.append(wx.Window(w, -1, rect.GetTopLeft(), (1, rect.height)))
        if rect.height > 1:
            lines.append(wx.Window(w, self.ID_HL, (rect.x, rect.y + rect.height - 1), (rect.width, 1)))
        if rect.width > 1:
            lines.append(wx.Window(w, self.ID_HL, (rect.x + rect.width - 1, rect.y), (1, rect.height)))
        for l in lines:
            l.SetBackgroundColour(colour)
            l.SetDropTarget(DropTarget(l))
        self.lines.extend(lines)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.