[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r8290 - in trunk/gnue-designer/src: base base/tools forms forms/P
From: |
jcater |
Subject: |
[gnue] r8290 - in trunk/gnue-designer/src: base base/tools forms forms/PagePainter uidrivers/wx uidrivers/wx/uihelpers |
Date: |
Mon, 3 Apr 2006 18:22:27 -0500 (CDT) |
Author: jcater
Date: 2006-03-30 09:01:28 -0600 (Thu, 30 Mar 2006)
New Revision: 8290
Added:
trunk/gnue-designer/src/forms/PagePainter/
trunk/gnue-designer/src/forms/PagePainter/PagePainter.py
trunk/gnue-designer/src/forms/PagePainter/PagePainterOGL.py
trunk/gnue-designer/src/forms/PagePainter/__init__.py
trunk/gnue-designer/src/uidrivers/wx/uihelpers/SimpleCanvas.py
Modified:
trunk/gnue-designer/src/base/Document.py
trunk/gnue-designer/src/base/ToolBase.py
trunk/gnue-designer/src/base/tools/TriggerEditor.py
trunk/gnue-designer/src/forms/Document.py
trunk/gnue-designer/src/uidrivers/wx/Base.py
Log:
more work on wx2.6-ifying, and de-gnue-forms-uidriver-ifying designer
(committing major changes that aren't 100% functional yet, so beware)
Modified: trunk/gnue-designer/src/base/Document.py
===================================================================
--- trunk/gnue-designer/src/base/Document.py 2006-03-30 08:15:26 UTC (rev
8289)
+++ trunk/gnue-designer/src/base/Document.py 2006-03-30 15:01:28 UTC (rev
8290)
@@ -69,15 +69,15 @@
#==========================================================================
wizardRunner = WizardRunner
- def init(self):
+ def init(self):
"""
- initialize the instance (called at the
+ initialize the instance (called at the
beginning of the __init__ process)
"""
- def init(self):
+ def init(self):
"""
- Finalize the instance (called at the
+ Finalize the instance (called at the
end of the __init__ process)
"""
@@ -164,20 +164,20 @@
def registerEditor(self, baseclass, gtype, filter=None):
"""
Register an editor class
-
- Parameters:
-
- baseclass: An EditorComponent class
-
- gtype: A string indicating a GObject._type identifier,
+
+ Parameters:
+
+ baseclass: An EditorComponent class
+
+ gtype: A string indicating a GObject._type identifier,
or a list of such strings.
-
+
filter: A function that is passed a GObject and should
return True/False indicating if an editor instance
should be created.
-
+
"""
- if isinstance(gtype,basestring):
+ if isinstance(gtype,basestring):
gtype = [gtype]
for gtype1 in gtype:
self._editorMapping[gtype1] = (filter, baseclass)
@@ -336,7 +336,7 @@
def __init__(self, app, location=None, buffer=None, style=None):
EventController.__init__(self)
-
+
self.app = app
self.ui = app.ui.createInstance(self)
@@ -344,7 +344,7 @@
# so we can execute them when everything has
# been initialized.
self.startCachingEvents()
-
+
# Local variables
self.wizardName = ""
self._isdirty = False
@@ -451,14 +451,14 @@
# Set up the editor components...
# ... common
- self.registerEditor(TriggerEditor.TriggerEditor, 'GCTrigger',
+ self.registerEditor(TriggerEditor.TriggerEditor, 'GCTrigger',
TriggerEditor.EditorFilter)
# ... and document-centric
self.createEditors()
# Create the document-centric tools
self.createTools()
-
+
# And tell the UI driver to create the UI portions
self.ui.initTools()
Modified: trunk/gnue-designer/src/base/ToolBase.py
===================================================================
--- trunk/gnue-designer/src/base/ToolBase.py 2006-03-30 08:15:26 UTC (rev
8289)
+++ trunk/gnue-designer/src/base/ToolBase.py 2006-03-30 15:01:28 UTC (rev
8290)
@@ -82,20 +82,20 @@
def __hide(self, event):
self._visible = False
# self.dockpane.hide()
-
+
# Used by UI-specific subclasses below
- def _createOuterInterfaces(self):
+ def _createOuterInterfaces(self):
pass
# ===========================================================================
# Notebook-based Component
# ===========================================================================
-class ToolNotebook(ToolBase):
+class ToolNotebook(ToolBase):
"""
Tool interfaces with a Notebook control as their outer component
"""
- def _createOuterInterfaces(self):
- notebook = self.notebook = NotebookCtrl.NotebookCtrl(self, -1,
+ def _createOuterInterfaces(self):
+ notebook = self.notebook = NotebookCtrl.NotebookCtrl(self, -1,
style=NotebookCtrl.NC_DEFAULT_STYLE|NotebookCtrl.NC_BOTTOM)
notebook.HideOnSingleTab()
notebook.EnableHiding()
@@ -103,15 +103,15 @@
notebook.SetPadding(wx.Size(1,1))
self.document.app.ui.autoSizer(self, notebook)
-
+
ToolBase._createOuterInterfaces(self)
- def addPage(self, page, text):
+ def addPage(self, page, text):
self.notebook.AddPage(page, text)
self.notebook.SetPageTextFont(self.notebook.GetPageCount()-1, wx.Font(9,
wx.DEFAULT, wx.NORMAL, wx.NORMAL, False))
return page
-
- def deletePage(self, id):
+
+ def deletePage(self, id):
return self.notebook.DeletePage(id)
Modified: trunk/gnue-designer/src/base/tools/TriggerEditor.py
===================================================================
--- trunk/gnue-designer/src/base/tools/TriggerEditor.py 2006-03-30 08:15:26 UTC
(rev 8289)
+++ trunk/gnue-designer/src/base/tools/TriggerEditor.py 2006-03-30 15:01:28 UTC
(rev 8290)
@@ -64,7 +64,6 @@
self.__ignoreevent = 0
- self.object = object
self.editor.SetReadOnly(0)
if not len(object._children):
@@ -104,7 +103,7 @@
# ===========================================================================
# Filter function
# ===========================================================================
-def EditorFilter(gctrigger):
+def EditorFilter(gctrigger):
assert gctrigger._type == 'GCTrigger'
return not gctrigger.src
Modified: trunk/gnue-designer/src/forms/Document.py
===================================================================
--- trunk/gnue-designer/src/forms/Document.py 2006-03-30 08:15:26 UTC (rev
8289)
+++ trunk/gnue-designer/src/forms/Document.py 2006-03-30 15:01:28 UTC (rev
8290)
@@ -55,6 +55,7 @@
from WizardRunner import WizardRunner
# Tool support...
+from PagePainter import PagePainter
from LayoutEditor import LayoutEditor
from TreeView import TreeView
from PropertyEditor import PropertyEditor
@@ -114,16 +115,16 @@
# Add our events/* stuff
registerEvents(self)
- def finalize(self):
+ def finalize(self):
# Convenience list to keep track of datasources and blocks
# TODO: Anything that needs either of these two
# TODO: should call getObjectList directly.
# TODO: Left for historical reasons.
self.datasources = self.getObjectList('datasource')
self.blocks = self.getObjectList('block')
-
-
+
+
# -------------------------------------------------------------------------
# Load a form
# -------------------------------------------------------------------------
@@ -149,7 +150,9 @@
# -------------------------------------------------------------------------
def createEditors(self):
# Associate our LayoutEditor with GFPage objects
+
self.registerEditor(LayoutEditor, 'GFPage')
+ self.registerEditor(PagePainter, 'GFPage')
def createTools(self):
Added: trunk/gnue-designer/src/forms/PagePainter/PagePainter.py
===================================================================
--- trunk/gnue-designer/src/forms/PagePainter/PagePainter.py 2006-03-30
08:15:26 UTC (rev 8289)
+++ trunk/gnue-designer/src/forms/PagePainter/PagePainter.py 2006-03-30
15:01:28 UTC (rev 8290)
@@ -0,0 +1,195 @@
+#
+# Copyright 2001-2006 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise 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, or (at your option) any later version.
+#
+# GNU Enterprise 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 program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id: TriggerEditor.py 8210 2006-03-07 00:04:31Z jcater $
+
+__all__ = ['PagePainter']
+
+#----------------------------------------------------------------------------
+# System Imports
+#----------------------------------------------------------------------------
+import sys
+import string
+
+#--------------------------------------------------------------------------
+# GNUe Imports
+#--------------------------------------------------------------------------
+from gnue.designer.base.EditorBase import EditorBase
+
+#--------------------------------------------------------------------------
+# External Imports
+#--------------------------------------------------------------------------
+import wx
+import SimpleCanvas
+
+
+xscale = 1
+yscale = 1
+
+
+# ===========================================================================
+# The PagePainter class
+# ===========================================================================
+class PagePainter (EditorBase):
+
+ runtime_section = "FormsPagePainter"
+ icon = 'painter'
+
+ def init(self, object):
+
+ canvas = self.canvas = MyCanvas(self)
+ self.document.app.ui.autoSizer(self, canvas)
+
+ self.object = object
+
+ self.setCaption(hasattr(object,'caption') and object.caption \
+ or object.name)
+
+ self.registerEventListeners({
+ # Object stuff
+ 'ObjectSelected' : self.__objectSelected,
+ 'ObjectCreated' : self.__objectCreated,
+ 'ObjectModified' : self.__objectModified,
+ 'ObjectDeleted' : self.__objectDeleted,
+ })
+
+ # Determine text extents
+ dc = wx.MemoryDC()
+ dc.SetFont(wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT))
+ global xscale, yscale
+
+ for char in string.digits + string.letters:
+ w, h = dc.GetTextExtent(char)
+ xscale = max(xscale, w)
+ yscale = max(yscale, h)
+
+
+ # Draw initial objects
+ self.object.walk(self.inventoryObject)
+
+
+ def inventoryObject(self, object):
+
+ canvas = self.canvas
+ try:
+ x,y = object['Char:x'], object['Char:y']
+ except:
+ return
+
+ try:
+ w,h = object['Char:width'], object['Char:height']
+ except:
+ w,h = object['Char:width'], object['Char:height'] = 10,1
+
+ print x, y, w, h
+ widget = MyObject(object, canvas)
+ canvas.Add(widget)
+ widget.SetSize(w*xscale,h*yscale)
+ widget.MoveTo(x*xscale,y*yscale)
+ print widget.bounds
+
+ def __objectSelected(self, object):
+ pass
+
+ def __objectCreated(self, object):
+ print "(Object Created)"
+
+ def __objectModified(self, object):
+ pass
+
+ def __objectDeleted(self, object):
+ pass
+
+
+import cPickle
+from gnue.designer.uidrivers.wx.uihelpers import SimpleCanvas
+
+
+class MyObject(SimpleCanvas.wxSimpleDrawableObject):
+ def __init__(self, object, canvas):
+ self.__object = object
+ SimpleCanvas.wxSimpleDrawableObject.__init__(self, canvas)
+
+ def Draw(self, dc):
+ dc.BeginDrawing()
+ dc.SetPen(wx.Pen(wx.BLACK))
+ wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
+ object = self.__object
+ x,y,w,h = self.bounds
+ dc.SetFont(wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT))
+ if object._type == 'GFLabel':
+ x = 0
+ for char in object.text:
+ dc.DrawText(char, x,0)
+ x += xscale
+ elif object._type == 'GFEntry':
+ dc.DrawRoundedRectangle(0,0,w,h, 1)
+ else:
+ dc.DrawRoundedRectangle(0,0,w,h, 4)
+
+ def DragHitTest (self, x, y):
+ if self.bounds.x <= x <= self.bounds.x + self.bounds.width and \
+ self.bounds.y <= y <= self.bounds.y + self.bounds.height:
+ return True
+ else:
+ return False
+
+ def ConvertDrawableObjectToDataObject (self, x, y):
+ object = self
+
+ data = [ { "Type" : "selectedWidgets",
+ "Attributes": {
+ 'startingX': x,
+ 'startingY': y,
+ }
+ }]
+# "name": dname,
+# "table": object.name,
+# "database": self.connectionName } }
+#
+#
+ do =
wx.CustomDataObject(wx.CustomDataFormat("application/x-gnue-designer"))
+ do.SetData(cPickle.dumps(data,1))
+
+ return do
+
+ def SelectedHitTest(self, x, y):
+ if self.bounds.x <= x <= self.bounds.x + self.bounds.width and \
+ self.bounds.y <= y <= self.bounds.y + self.bounds.height:
+ return True
+ else:
+ return False
+
+
+class MyCanvas(SimpleCanvas.wxSimpleCanvas):
+ def DrawBackground(self, dc):
+ dc.BeginDrawing()
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ dc.Clear()
+
+ # Draw the grid (TODO: make this settable)
+ w, h = self.GetClientSizeTuple()
+ dc.SetPen(wx.Pen(wx.Colour(240,240,240)))
+ for x in range(0,w,xscale):
+ dc.DrawLine(x,0,x,h-1)
+
+ for y in range(0,h, yscale):
+ dc.DrawLine(0,y,w,y)
+ dc.EndDrawing()
Added: trunk/gnue-designer/src/forms/PagePainter/PagePainterOGL.py
===================================================================
--- trunk/gnue-designer/src/forms/PagePainter/PagePainterOGL.py 2006-03-30
08:15:26 UTC (rev 8289)
+++ trunk/gnue-designer/src/forms/PagePainter/PagePainterOGL.py 2006-03-30
15:01:28 UTC (rev 8290)
@@ -0,0 +1,113 @@
+#
+# Copyright 2001-2006 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise 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, or (at your option) any later version.
+#
+# GNU Enterprise 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 program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id: TriggerEditor.py 8210 2006-03-07 00:04:31Z jcater $
+
+__all__ = ['PagePainter']
+
+#----------------------------------------------------------------------------
+# System Imports
+#----------------------------------------------------------------------------
+import sys
+import math
+
+#--------------------------------------------------------------------------
+# GNUe Imports
+#--------------------------------------------------------------------------
+from gnue.designer.base.EditorBase import EditorBase
+
+#--------------------------------------------------------------------------
+# External Imports
+#--------------------------------------------------------------------------
+import wx
+from wx.glcanvas import GLCanvas
+
+from OpenGL.GLUT import *
+from OpenGL.GLU import *
+from OpenGL.GL import *
+
+
+
+# ===========================================================================
+# The PagePainter class
+# ===========================================================================
+class PagePainter (EditorBase):
+
+ runtime_section = "FormsPagePainter"
+ icon = 'painter'
+
+ def init(self, object):
+
+ canvas = self.canvas = GLCanvas(self)
+ self.document.app.ui.autoSizer(self, canvas)
+
+ self.object = object
+
+ self.setCaption(hasattr(object,'caption') and object.caption \
+ or object.name)
+
+
+ #----------------------------------------------------------------------
+ # wxPython + OpenGL integration
+ #----------------------------------------------------------------------
+ wx.EVT_SIZE(canvas,self.__onResize)
+ wx.EVT_PAINT(canvas,self.__onPaint)
+ wx.EVT_ERASE_BACKGROUND(canvas, self.__onEraseBackground)
+
+
+ #--------------------------------------------------------------------------
+ # wxPython + OpenGL integration
+ #--------------------------------------------------------------------------
+ def drawCanvas(self):
+ print "Drawing!"
+
+
+ #--------------------------------------------------------------------------
+ # wxPython + OpenGL integration
+ #--------------------------------------------------------------------------
+ def __onResize(self, event):
+ size = self.canvas.GetClientSize()
+ if self.canvas.GetContext():
+ self.canvas.SetCurrent()
+ glViewport(0, 0, size.width, size.height)
+
+ def __onEraseBackground(self, event):
+ pass # Avoids flicker
+
+ def __onPaint(self, *args):
+ dc = wx.PaintDC(self.canvas)
+ self.__redraw(None)
+
+ def __redraw(self, *args):
+ #dc = wxPaintDC(self)
+ dc = wx.ClientDC(self.canvas)
+ self.canvas.SetCurrent()
+
+ mode = glGetDouble(GL_MATRIX_MODE)
+ glMatrixMode(GL_PROJECTION)
+
+ glPushMatrix()
+ self.drawCanvas()
+ glFlush()
+ glPopMatrix()
+ self.canvas.SwapBuffers()
+
+ glMatrixMode(mode)
+
Added: trunk/gnue-designer/src/forms/PagePainter/__init__.py
===================================================================
--- trunk/gnue-designer/src/forms/PagePainter/__init__.py 2006-03-30
08:15:26 UTC (rev 8289)
+++ trunk/gnue-designer/src/forms/PagePainter/__init__.py 2006-03-30
15:01:28 UTC (rev 8290)
@@ -0,0 +1 @@
+from PagePainter import *
Modified: trunk/gnue-designer/src/uidrivers/wx/Base.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/Base.py 2006-03-30 08:15:26 UTC
(rev 8289)
+++ trunk/gnue-designer/src/uidrivers/wx/Base.py 2006-03-30 15:01:28 UTC
(rev 8290)
@@ -95,7 +95,7 @@
# This has to happen after setWxApp, otherwise bad things happen
from gnue.forms.uidrivers.wx import UILoginHandler
self.app.getConnectionManager().setLoginHandler(UILoginHandler())
-
+
# Call wx's MainLoop
self.app.init()
Added: trunk/gnue-designer/src/uidrivers/wx/uihelpers/SimpleCanvas.py
===================================================================
--- trunk/gnue-designer/src/uidrivers/wx/uihelpers/SimpleCanvas.py
2006-03-30 08:15:26 UTC (rev 8289)
+++ trunk/gnue-designer/src/uidrivers/wx/uihelpers/SimpleCanvas.py
2006-03-30 15:01:28 UTC (rev 8290)
@@ -0,0 +1,602 @@
+#
+# Copyright 2001-2006 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise 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, or(at your option) any later version.
+#
+# GNU Enterprise 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 program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id: TriggerEditor.py 8210 2006-03-07 00:04:31Z jcater $
+
+#
+# These classes are based on SimpleCanvas from OSA's Chandler
+# application, but heavily commented and debugged.
+#
+
+import wx
+import time
+
+
+# ===================================================================
+# A Drawable canvas widget
+# ===================================================================
+class wxSimpleDrawableObject(wx.EvtHandler):
+ def __init__(self, canvas):
+ super(wxSimpleDrawableObject, self).__init__()
+
+ self.bounds = wx.Rect()
+ self.canvas = canvas
+ self.visible = True
+ self.selected = False
+ self.dragStartPos = None
+
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+
+ def MoveTo(self, x, y):
+ self.canvas.RefreshScrolledRect(self.bounds);
+ self.bounds.SetLeft(x)
+ self.bounds.SetTop(y)
+ self.canvas.RefreshScrolledRect(self.bounds);
+
+ def SetSize(self, width, height):
+ self.canvas.RefreshScrolledRect(self.bounds);
+ self.bounds.SetWidth(width)
+ self.bounds.SetHeight(height)
+ self.canvas.RefreshScrolledRect(self.bounds);
+
+ def OnMouseEvent(self, event):
+ x, y = event.GetPositionTuple()
+ print "(x,y)=(%s,%s)" % (x,y)
+ if event.ButtonDown(1):
+ if self.SelectedHitTest(x, y) :
+ self.canvas.DeSelectAll()
+ self.SetSelected()
+ self.canvas.Update()
+ if self.DragHitTest(x, y):
+ self.dragStartPos =(x, y)
+ else:
+ self.dragStartPos =(x,y)
+ elif event.ButtonUp(1):
+ self.dragStartPos = None
+ elif event.Dragging() and event.LeftIsDown():
+ tolerance = 2
+ if abs(x - self.dragStartPos[0]) > tolerance or abs(y -
self.dragStartPos[1]) > tolerance:
+ self.DoDrag(x, y)
+ return True
+ event.Skip()
+ return False
+
+ def SetBounds(self, bounds):
+ self.canvas.RefreshScrolledRect(self.bounds);
+ self.bounds = bounds
+ self.canvas.RefreshScrolledRect(self.bounds);
+
+ def Show(self, show):
+
+ # Make sure show is a Boolean
+ show = bool(show)
+
+ if(show ^ self.visible):
+ self.visible = show
+ self.canvas.RefreshScrolledRect(self.bounds);
+ self.canvas.Update()
+
+ def ConvertToCanvasDeviceCoordinates(self, x, y):
+ return self.canvas.CalcScrolledPosition(self.bounds.GetLeft() + x,
+ self.bounds.GetTop() + y)
+
+ def DoDrag(self, x, y):
+ """
+ Implement all the drag and drop functionality:
+ """
+
+ """
+ Create the dragImage and begin dragging over the full screen
+ """
+ offscreenBuffer = wx.EmptyBitmap(self.bounds.GetWidth(),
self.bounds.GetHeight())
+ memoryDC = wx.MemoryDC()
+ memoryDC.SelectObject(offscreenBuffer)
+
+ memoryDC.BeginDrawing()
+ memoryDC.Clear()
+ self.Draw(memoryDC)
+
+ maskBitmap = wx.EmptyBitmap(self.bounds.GetWidth(),
self.bounds.GetHeight(), 1)
+ memoryDC.SelectObject(maskBitmap)
+
+ memoryDC.SetBackground(wx.BLACK_BRUSH)
+ memoryDC.Clear()
+
+ self.DrawMask(memoryDC)
+ memoryDC.EndDrawing()
+
+ memoryDC.SelectObject(wx.NullBitmap)
+
+ if "__WXMAC__" in wx.PlatformInfo: # workaround for wxMac bug
+ offscreenBuffer.SetMask(wx.MaskColour(maskBitmap, wx.BLACK))
+ else:
+ offscreenBuffer.SetMask(wx.Mask(maskBitmap))
+
+ """
+ Create the dragImage and begin dragging
+ """
+ if "__WXGTK__" in wx.PlatformInfo:
+ # The "hole punching" trick dosen't work on wxGTK, move the hostspot
+ # to be just outside the image
+ x, y = -1, -1
+ self.dragImage = wxCanvasDragImage(offscreenBuffer)
+
+ self.dragImage.BeginDrag(wx.Point(x,y), self.canvas, True)
+ self.dragImage.Move(self.ConvertToCanvasDeviceCoordinates(x, y))
+ self.dragImage.Show()
+
+ """
+ We need to keep a reference to the dataObject, rather than create
+ it in the construction because wxCanvasDropSource doesn't own the
+ data so the garbage collector will delete it.
+ """
+ dataObject = self.ConvertDrawableObjectToDataObject(x, y)
+ dropSource = wxCanvasDropSource(self, dataObject)
+
+ self.canvas.internalDnDItem = self
+ result = dropSource.DoDragDrop(wx.Drag_AllowMove)
+ self.canvas.internalDnDItem = None
+ self.dragImage.Hide()
+ self.dragImage.EndDrag()
+ del self.dragImage
+
+ def DrawMask(self, dc):
+ """
+ optionally implement this routine to draw a mask
+ """
+ pass
+
+ def SizeDrag(self, dragRect, startDrag, endDrag):
+ self.canvas.RefreshScrolledRect(self.bounds)
+ self.bounds = dragRect
+ self.canvas.RefreshScrolledRect(self.bounds)
+
+ """
+ You must implement the following functions
+ """
+ def Draw(self, dc):
+ """
+ You must implement this routine to do draw
+ """
+ assert(False)
+
+ def DragHitTest(self, x, y):
+ """
+ You must implement this routine to do hit testing for dragable region
+ of drawable object
+ """
+ assert(False)
+
+ def ConvertDrawableObjectToDataObject(self, x, y):
+ """
+ You must implement this routine to create data object for drag and drop
+ """
+ assert(False)
+
+ def SelectedHitTest(self, x, y):
+ """
+ You must implement this routine to do hit testing to identify the region
+ for selecting the object.
+ """
+ assert(False)
+
+ def SetSelected(self, selected=True):
+ """
+ Sets the selected bit for this object. Does a canvas refresh on the object
+ if it has changed state. Does not call Update on the canvas.
+ """
+ # Use the same trick as Show()
+ selected = bool(selected)
+
+ # Only do a refresh if we've changed state.
+ if(selected ^ self.selected):
+ self.selected = selected
+ self.canvas.RefreshScrolledRect(self.bounds);
+
+
+# ===================================================================
+# The canvas to draw on
+# ===================================================================
+class wxSimpleCanvas(wx.ScrolledWindow):
+ def __init__(self, *arguments, **keywords):
+ super(wxSimpleCanvas, self).__init__(*arguments, **keywords)
+
+ self.autoCreateDistance = 0
+ self.zOrderedDrawableObjects = []
+ self.internalDnDItem = None
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
+ self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+
+
+ def __del__(self):
+ for item in self.zOrderedDrawableObjects:
+ item.Destroy()
+
+ def RefreshScrolledRect(self, rect):
+ position = rect.GetPosition()
+ x, y = self.CalcScrolledPosition(position.x, position.y)
+ self.RefreshRect(wx.Rect(x, y, rect.GetWidth(), rect.GetHeight()));
+
+ def OnPaint(self, event):
+ """
+ wx.BufferedDC doesn't work here since it doesn't handle scrolled windows
+ and always allocates a buffer the size of the client area. So instead we'll
+ allocate a wx.MemoryDC, draw into it then blit it to our paintDC.
+ Eventually, if we're printing, we should bypass the wx.MemoryDC.
+ The updateRegion is not in scrolled coordinates.
+ """
+ scrollWindowOriginX, scrollWindowOriginY = self.CalcUnscrolledPosition(0,
0)
+
+ paintDC = wx.PaintDC(self)
+ self.PrepareDC(paintDC)
+
+ """
+ Calculate the rectangle that needs updating in scrolled coordinates
+ """
+ updateRect = self.GetUpdateRegion().GetBox()
+ bufferX = updateRect.GetLeft() + scrollWindowOriginX
+ bufferY = updateRect.GetTop() + scrollWindowOriginY
+ bufferWidth = updateRect.GetWidth()
+ bufferHeight = updateRect.GetHeight()
+
+ memoryDC = wx.MemoryDC()
+ offscreenBuffer = wx.EmptyBitmap(bufferWidth, bufferHeight)
+ memoryDC.SelectObject(offscreenBuffer)
+ memoryDC.SetDeviceOrigin(-bufferX, -bufferY)
+
+ """
+ Debugging code that makes it easy to see which areas are updating.
+ """
+ if 0:
+ success = paintDC.Blit(bufferX, bufferY,
+ bufferWidth, bufferHeight,
+ paintDC,
+ bufferX, bufferY,
+ wx.SRC_INVERT)
+ time.sleep(1)
+ success = paintDC.Blit(bufferX, bufferY,
+ bufferWidth, bufferHeight,
+ paintDC,
+ bufferX, bufferY,
+ wx.SRC_INVERT)
+
+
+ memoryDC.BeginDrawing()
+
+ self.DrawBackground(memoryDC)
+ self.Draw(memoryDC)
+
+ paintDC.Blit(bufferX, bufferY,
+ bufferWidth, bufferHeight,
+ memoryDC,
+ bufferX, bufferY)
+
+ memoryDC.EndDrawing()
+
+ def Draw(self, dc):
+ updateRegion = self.GetUpdateRegion()
+ scrollWindowOriginX, scrollWindowOriginY = self.CalcUnscrolledPosition(0,
0)
+ dcOriginX, dcOriginY = dc.GetDeviceOrigin()
+ index = len(self.zOrderedDrawableObjects) - 1
+ while index >= 0:
+ drawableObject = self.zOrderedDrawableObjects [index]
+ objectX = drawableObject.bounds.GetLeft()
+ objectY = drawableObject.bounds.GetTop()
+ objectWidth = drawableObject.bounds.GetWidth()
+ objectHeight = drawableObject.bounds.GetHeight()
+
+ bounds = wx.Rect(objectX - scrollWindowOriginX,
+ objectY - scrollWindowOriginY,
+ objectWidth,
+ objectHeight)
+
+ if updateRegion.ContainsRect(bounds) != wx.OutRegion and
drawableObject.visible:
+ dc.SetDeviceOrigin(objectX + dcOriginX, objectY + dcOriginY)
+ drawableObject.Draw(dc)
+ dc.SetDeviceOrigin(dcOriginX, dcOriginY)
+ index -= 1
+
+ def OnEraseBackground(self, event):
+ """
+ Override OnEraseBackground to avoid erasing background. Instead
+ implement OnDrawBackground to draw/erase the background. This
+ design alternative will eliminate flicker
+ """
+ pass
+
+ def OnMouseEvent(self, event):
+ x, y = event.GetPositionTuple()
+ x, y = self.CalcUnscrolledPosition(x, y)
+ for drawableObject in self.zOrderedDrawableObjects:
+ if drawableObject.bounds.Inside((x, y)):
+ event.m_x = x - drawableObject.bounds.GetX()
+ event.m_y = y - drawableObject.bounds.GetY()
+ if drawableObject.ProcessEvent(event):
+ return True
+
+ if self.autoCreateDistance != 0:
+ if event.ButtonDown() and self.CreateHitTest(x, y):
+ self.dragStart = wx.Point(x, y)
+ self.CaptureMouse()
+ return True
+ elif hasattr(self, 'dragStart'):
+ if event.Dragging():
+ """
+ Clip mouse position to the scrolling window's bounds
+ """
+ boundsX, boundsY = self.GetVirtualSizeTuple()
+ if x < 0:
+ x = 0
+ if x > boundsX:
+ x = boundsX
+ if y < 0:
+ y = 0
+ if y > boundsY:
+ y = boundsY
+
+ deltaX = x - self.dragStart.x
+ deltaY = y - self.dragStart.y
+
+ if deltaX >= 0:
+ left = self.dragStart.x
+ width = deltaX
+ else:
+ left = x
+ width = -deltaX
+
+ if deltaY >= 0:
+ top = self.dragStart.y
+ height = deltaY
+ else:
+ top = y
+ height = -deltaY
+ dragRect = wx.Rect(left, top, width, height)
+
+ if not hasattr(self, 'dragCreateDrawableObject'):
+ if(deltaX * deltaX) +(deltaY * deltaY) >(self.autoCreateDistance *
self.autoCreateDistance):
+ """
+ Create a new drawable object if we've dragged autoCreateDistance
+ pixels
+ """
+ object = self.dragCreateDrawableObject =
self.CreateNewDrawableObject(dragRect,
+
self.dragStart,
+
wx.Point(x, y))
+ # if we weren't allowed to create one, give up
+ if object is None:
+ return True
+
+ self.DeSelectAll()
+ object.selected = True
+
+
+ #self.zOrderedDrawableObjects.insert(0,
self.dragCreateDrawableObject)
+ #self.RefreshScrolledRect(self.dragCreateDrawableObject.bounds);
+ self.Add(object)
+
+ return True
+ else:
+ if self.dragCreateDrawableObject != None:
+ self.dragCreateDrawableObject.SizeDrag(dragRect,
+ self.dragStart,
+ wx.Point(x, y))
+
+ elif event.ButtonUp():
+ del self.dragStart
+ if hasattr(self, 'dragCreateDrawableObject'):
+ del self.dragCreateDrawableObject
+ self.ReleaseMouse()
+ return True
+ return False
+
+ def OnData(self, dataObject, x, y, result):
+ """
+ Handle default behavior of copy and move
+ """
+ if result == wx.DragMove or result == wx.DragCopy:
+ if(self.internalDnDItem != None) and(result == wx.DragMove):
+ assert(self.zOrderedDrawableObjects.count(self.internalDnDItem) ==
1)
+
+ drawableObject =
self.ConvertDataObjectToDrawableObject(dataObject, x, y, True)
+ x = drawableObject.bounds.GetLeft()
+ y = drawableObject.bounds.GetTop()
+
+ self.zOrderedDrawableObjects.remove(self.internalDnDItem)
+ self.zOrderedDrawableObjects.insert(0, self.internalDnDItem)
+ self.internalDnDItem.MoveTo(x, y)
+ self.internalDnDItem.Show(True)
+ else:
+
+ drawableObject =
self.ConvertDataObjectToDrawableObject(dataObject, x, y, False)
+ x = drawableObject.bounds.GetLeft()
+ y = drawableObject.bounds.GetTop()
+
+ self.zOrderedDrawableObjects.insert(0, drawableObject)
+ self.RefreshScrolledRect(drawableObject.bounds);
+ return result
+
+ def CreateHitTest(self, x, y):
+ """
+ Set self.autoCreateDistance to some value other than zero to enable
+ dragging autoCreateDistance pixels to automatically create new drawable
+ objects.
+ By default, drawable objects are created if you click and drag in the
+ canvas anwhere there isn't a drawable object. You can restrict this
location
+ that drawable objects are created by overriding this routine
+ """
+ return True
+ """
+ You must implement the following functions
+ """
+ def ConvertDataObjectToDrawableObject(self, dataObject, x, y, move):
+ """
+ You must implement this routine to convert a dataobject, used in
+ drag and drop into a drawable object.
+ """
+ assert(False)
+
+ def CreateNewDrawableObject(self, dragRect, startDrag, endDrag):
+ """
+ You must implement this routine to create new drawable objects by
+ dragging on the blank canvas.
+ """
+ assert(False)
+
+ def DeSelectAll(self):
+ """
+ Mark all selected objects as not selected. Only Refresh the objects
+ that change, don't call Update.
+ """
+ for drawableObject in self.zOrderedDrawableObjects:
+ if(drawableObject.selected):
+ drawableObject.selected = False
+ self.RefreshScrolledRect(drawableObject.bounds)
+
+ # -----------------------------------------------------------------
+ # Additions by GNUe
+ # -----------------------------------------------------------------
+ def Add(self, object):
+ """
+ Add a DrawableObject to the canvas
+ """
+ self.zOrderedDrawableObjects.insert(0, object)
+ self.RefreshScrolledRect(object.bounds);
+
+ def Remove(self, object):
+ self.zOrderedDrawableObjects.remove(object)
+ bounds = object.bounds
+ self.RefreshScrolledRect(bounds)
+ object.Destroy()
+
+
+# ===================================================================
+# A draggable image frame
+# ===================================================================
+class wxCanvasDragImage(wx.Frame):
+ """
+ A class similar to wx.DragImage except that it uses a shaped frame
+ to display the image, and that it is always full screen.
+ """
+ def __init__(self, bitmap):
+ super(wxCanvasDragImage, self).__init__(
+ None, -1, "",
+ style = wx.FRAME_SHAPED
+ | wx.SIMPLE_BORDER
+ | wx.FRAME_NO_TASKBAR
+ | wx.STAY_ON_TOP)
+ self.bmp = bitmap
+ w, h = self.bmp.GetWidth(), self.bmp.GetHeight()
+ self.SetClientSize((w, h) )
+ self.hotspot = None
+ self.window = None
+
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ if "__WXGTK__" in wx.PlatformInfo:
+ # wxGTK requires that the window be created before you can
+ # set its shape, so delay the call to SetWindowShape until
+ # this event.
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
+ else:
+ # On wxMSW and wxMac the window has already been created, so go for it.
+ self.SetWindowShape()
+
+ def SetWindowShape(self, evt=None, hotspot=None):
+ # Use the bitmap's mask to determine the region
+ rgn = wx.RegionFromBitmap(self.bmp)
+ if hotspot is not None:
+ # punch a hole in the region at the hotspot to allow mouse events
+ # through to the window below
+ rect = wx.Rect(hotspot.x-1, hotspot.y-1, 3, 3)
+ rgn.SubtractRect(rect)
+ self.SetShape(rgn)
+
+ def BeginDrag(self, hotspot, window, *ignoreOthers):
+ self.hotspot = wx.Point(hotspot[0], hotspot[1])
+ if "__WXGTK__" not in wx.PlatformInfo:
+ self.SetWindowShape(hotspot = self.hotspot)
+ self.window = window
+ if self.window:
+ self.window.CaptureMouse()
+
+ def EndDrag(self, doDestroy=True):
+ if self.window and self.window.HasCapture():
+ self.window.ReleaseMouse()
+ self.Hide()
+ if doDestroy:
+ self.Destroy()
+
+ def Move(self, pt):
+ """
+ Move the image to a new location on screen. The pt parameter
+ is a point in client coordinants relative to the window
+ specifed in BeginDrag. (Only for compatibility with
+ wx.DragImage, otherwise I would just use screen coordinants...)
+ """
+ pt2 = pt
+ if self.window:
+ pt2 = self.window.ClientToScreen(pt)
+ self.SetPosition(pt2 - self.hotspot)
+
+ def Show(self):
+ wx.Frame.Show(self)
+ self.Update()
+
+ def OnPaint(self, evt):
+ dc = wx.PaintDC(self)
+ dc.DrawBitmap(self.bmp, 0, 0, True)
+
+
+# ===================================================================
+# A draggable drop source
+# ===================================================================
+class wxCanvasDropSource(wx.DropSource):
+ def __init__(self, drawableObject, dataObject):
+ super(wxCanvasDropSource, self).__init__(drawableObject.canvas)
+ self.drawableObject = drawableObject
+ self.SetData(dataObject)
+
+ def GiveFeedback(self, effect):
+ windowX, windowY = wx.GetMousePosition()
+ self.drawableObject.Show(effect != wx.DragMove)
+ x, y = self.drawableObject.canvas.ScreenToClientXY(windowX, windowY)
+ self.drawableObject.dragImage.Move((x, y))
+ return False
+
+
+# ===================================================================
+# A draggable drop target
+# ===================================================================
+class wxCanvasDropTarget(wx.PyDropTarget):
+ def __init__(self, canvas, dropTargetDataObject):
+ super(wxCanvasDropTarget, self).__init__()
+ self.canvas = canvas
+ self.dataObject = dropTargetDataObject
+ self.SetDataObject(dropTargetDataObject)
+
+ def OnData(self, x, y, result):
+ """
+ Delegate functionality to the canvas
+ """
+ if(self.GetData()):
+ x, y = self.canvas.CalcUnscrolledPosition(x, y)
+ result = self.canvas.OnData(self.dataObject, x, y, result)
+ return result
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r8290 - in trunk/gnue-designer/src: base base/tools forms forms/PagePainter uidrivers/wx uidrivers/wx/uihelpers,
jcater <=