[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
CVSROOT: /cvsroot/gnue
From: |
Jason Cater |
Subject: |
CVSROOT: /cvsroot/gnue |
Date: |
Fri, 22 Aug 2003 20:04:43 -0400 |
Module name: gnue-designer
Branch: layout-editor-rendering
Changes by: Jason Cater <address@hidden> 03/08/22 20:04:42
Reply-to: address@hidden
CVSROOT: /cvsroot/gnue
Module name: gnue-designer
Branch: layout-editor-rendering
Changes by: Jason Cater <address@hidden> 03/08/22 20:04:42
Modified files:
src/forms/LayoutEditor: LayoutEditor.py
src/forms/LayoutEditor/renderers/Base: Driver.py GridPane.py
src/forms/LayoutEditor/renderers/curses: Driver.py
src/forms/LayoutEditor/renderers/native: Driver.py
WidgetHandler.py
Log message:
(branched) Splitting LayoutEditor into various smaller components and
adding Renderer support
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-designer/src/forms/LayoutEditor/LayoutEditor.py.diff?only_with_tag=layout-editor-rendering&tr1=1.97&tr2=1.97.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-designer/src/forms/LayoutEditor/renderers/Base/Driver.py.diff?only_with_tag=layout-editor-rendering&tr1=1.1&tr2=1.1.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-designer/src/forms/LayoutEditor/renderers/Base/GridPane.py.diff?only_with_tag=layout-editor-rendering&tr1=1.7&tr2=1.7.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-designer/src/forms/LayoutEditor/renderers/curses/Driver.py.diff?only_with_tag=layout-editor-rendering&tr1=1.1&tr2=1.1.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-designer/src/forms/LayoutEditor/renderers/native/Driver.py.diff?only_with_tag=layout-editor-rendering&tr1=1.1&tr2=1.1.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-designer/src/forms/LayoutEditor/renderers/native/WidgetHandler.py.diff?only_with_tag=layout-editor-rendering&tr1=1.15&tr2=1.15.4.1&r1=text&r2=text
Patches:
Index: gnue-designer/src/forms/LayoutEditor/LayoutEditor.py
diff -c /dev/null gnue-designer/src/forms/LayoutEditor/LayoutEditor.py:1.97.4.1
*** /dev/null Fri Aug 22 20:04:43 2003
--- gnue-designer/src/forms/LayoutEditor/LayoutEditor.py Fri Aug 22
20:04:42 2003
***************
*** 0 ****
--- 1,833 ----
+ #
+ # 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.
+ #
+ # Copyright 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # LayoutEditor.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ # TODO: Split this file up
+ #
+
+ __all__ = ['LayoutEditor']
+
+ import sys, os
+ from wxPython.wx import *
+ from gnue.common.apps import GDebug
+ from gnue.forms import GFObjects
+ from gnue.forms.uidrivers.wx import UIdriver as UIwxpython
+ from gnue.designer.base.PopupMenu import PageMenu
+ from gnue.designer.base.TemplateParser import TemplateParser
+ from gnue.designer.base.ToolBase import *
+ from gnue.common.events import Event
+
+ # My support files
+ from Utils import *
+ from LayoutEditorTools import LayoutEditorTools
+ from PropertyBar import PropertyBar
+ from DisplayDropTarget import DisplayDropTarget
+ from ReorderFocus import ReorderFocus
+
+ from renderers.native.WidgetHandler import WidgetHandler
+ from renderers.Base.GridPane import GridPane
+ from renderers.native.Driver import Renderer
+
+ from Workspace import Workspace
+
+ class LayoutEditor (ToolBase):
+
+ runtime_section = "FormsLayoutEditor"
+ default_dock = 'right-0'
+ uses_feedback_bar = 1
+ uses_toolbar = 1
+
+
+ def init(self):
+
+ self.renderer = Renderer(self.instance)
+
+ # TODO: blah.... historical reasons
+ self._instance = self.instance
+
+ self._app = self.instance._app
+
+ self.page = None
+ self.block = None
+ self.lastBlock = None
+ self.blockMap = {}
+ self.panel = None
+ self._notebookMap = {}
+ self.positionMappings = {}
+ self.widgetList = []
+ self._currentSelection = []
+
+ # Create our own WX GFUserInterface instance
+ self.uidriver = uidriver = UIwxpython.GFUserInterface(self.instance, 0)
+
+ # Create a list of all UI widgets
+ self.widgets = {}
+ self.widgets.update(uidriver._supportedWidgets)
+
+ # But we don't want a page to act like normal objects...
+ # we have special plans for it (bwahahaha)
+ del self.widgets['GFPage']
+
+
+ self.notebook = wxNotebook(self, -1, pos=wxPoint(4, 4),
size=wxSize(32,32))
+ self.backcolor = wxWHITE
+
+ EVT_NOTEBOOK_PAGE_CHANGED(self,self.notebook.GetId(), self.OnPageSelected)
+ EVT_SIZE(self, self.OnSize)
+
+ self._currentObject = None
+ self.mode = 'move'
+ self.reorderfocus = ReorderFocus(self.instance)
+
+ # Internal mouse states... used by OnMotion, etc
+ self.__drawing = 0
+ self.__x = 0
+ self.__y = 0
+ self.__ox = 0
+ self.__oy = 0
+
+ # EventAware provided by ToolBase
+ self.registerEventListeners({
+ 'ObjectSelected' : self.onSetCurrentObject,
+ 'ObjectCreated' : self.onCreateObject,
+ 'ObjectModified' : self.onModifyObject,
+ 'ObjectDeleted' : self.onDeleteObject,
+ 'LayoutEditor:ZoomIn' : self.zoomIn,
+ 'LayoutEditor:ZoomOut': self.zoomOut,
+ 'LayoutEditor:FocusOrder': self.beginFocusOrder,
+ 'Cancel:LayoutEditor:FocusOrder': self.endFocusOrder,
+ 'LayoutEditor:Prepositioning':
self.beginPrePositioningTemplate,
+ 'Cancel:LayoutEditor:Prepositioning':
self.cancelPrePositioningTemplate,
+ 'LayoutEditor:Select': self.beginSelectMode,
+ 'Cancel:LayoutEditor:Select': self.cancelSelectMode,
+ 'EndWizard': self.endWizard,
+ })
+
+ self.instance.rootObject.walk (self.inventoryObject)
+ try:
+ self._setCurrentPage(self._notebookMap[0])
+ except KeyError:
+ pass
+
+ ## Stuff needed by UIwxpython
+ self._pageList = [] # Needed by UIwxpython
+
+
+ def createToolbar(self, parent):
+ self.toolbar = LayoutEditorTools(parent, self.instance)
+ self.blockCombo = self.toolbar.blockCombo
+ EVT_COMBOBOX(self.toolbar, self.blockCombo.GetId(), self.OnBlockSelected)
+ self._rebuildBlockCombo()
+ return self.toolbar
+
+ # Recalculate the scrollbar sizes
+ def __OnGridSize(self, event):
+ w, h = self.panel.GetSizeTuple()
+ w2, h2 = self.workspacescroll.GetClientSizeTuple()
+ w = int(max(w, w2)*1.1+30)
+ h = int(max(h, h2)*1.1+30)
+ self.workspace.SetSize((w,h))
+ self.workspacescroll.SetScrollbars(w/30-1,h/30-1,30,30)
+
+
+ def inventoryObject(self, object):
+ if object._type == 'GFPage':
+ index = self.notebook.GetPageCount()
+ self._notebookMap[object] = index
+ self._notebookMap[index] = object
+
+ self.workspace = Workspace(self.notebook, self, object)
+
+ self.notebook.AddPage(self.workspace.scroller, object.name)
+ object.__workspace = self.workspace
+
+ elif object._type == 'GFBlock':
+ self.blockMap[object.name.lower()] = object
+ if not self.block:
+ self._setCurrentBlock(object)
+
+
+ def onSetCurrentObject (self, event):
+ object = event.object
+ handler = event.originator
+
+ try:
+ selection = event.selection
+ except:
+ selection = [object]
+
+ self._currentObject = object
+
+ if handler != "Forms::LayoutEditor":
+ self._setCurrentPage(object)
+ self._setFeedback()
+ self._setCurrentBlock(object)
+ self._setSelection(object, selection)
+
+ def _setCurrentBlock(self,object):
+ if not object:
+ return
+ block = object.findParentOfType('GFBlock')
+ if not block:
+ if object._type == 'GFEntry':
+ block = object._block
+ if block:
+ self.block = block
+ if hasattr(self,'blockCombo'):
+ self.blockCombo.SetValue(block.name)
+ ## self._setFeedback()
+
+ def _rebuildBlockCombo(self):
+ if hasattr(self,'blockCombo'):
+ # TODO
+ srt = self.blockMap.keys()
+ srt.sort()
+ self.blockComboList = []
+ self.blockCombo.Clear()
+
+ for key in srt:
+ block = self.blockMap[key]
+ self.blockCombo.Append(block.name)
+ self.blockComboList.append(block)
+ if self.block:
+ self.blockCombo.SetValue(self.block.name)
+
+ def OnBlockSelected(self, event):
+ s= event.GetSelection()
+ block = self.blockComboList[s]
+ if block != self.block:
+ self.dispatchEvent('ObjectSelected',
+ object = block,
+ originator = None)
+
+ def _setFeedback(self):
+
+ object = self._currentObject
+
+ ft = ""
+
+ # This sets the feedback text at the top of the Layout Editor window
+ if object:
+ try: ft += 'Name: % (%s)' % (object.name, object._type[2:])
+ except: pass
+
+ try: ft += ' Col: %s' % object.Char__x
+ except: pass
+
+ try: ft += ' Row: %s' % object.Char__y
+ except: pass
+
+ try: ft += ' Width: %s' % object.Char__width
+ except: pass
+
+ try:
+ if object.Char__height > 1:
+ ft += ' Height: %s' % object.Char__height
+ except:
+ pass
+
+ if ft:
+ self.setFeedback(ft)
+
+
+ def _setCurrentPage(self, object):
+ if not object:
+ return
+ page = isinstance(object, GFObjects.GFPage) and object or \
+ object.findParentOfType('GFPage')
+
+ if page != None and page != self.page:
+ self.page = page
+ self.workspace = page.__workspace
+ self.notebook.SetSelection(self._notebookMap[page])
+
+
+ def _setSelection(self, focus, objects):
+
+ # Unhighlight any previously selected items
+ # that are no longer selected.
+ for key in self._currentSelection:
+ if key not in objects:
+ try:
+ key._widgetHandler.setSelected(0)
+ except AttributeError:
+ pass
+
+ # and now highlight any new items
+ for object in objects:
+ if hasattr(object, '_widgetHandler') and object not in
self._currentSelection:
+ self._currentSelection.append(object)
+ object._widgetHandler.setSelected(1, object == focus)
+
+ self._currentSelection = objects[:]
+
+
+ def onCreateObject (self, event):
+ object = event.object
+ handler = event.originator
+ ## self._currentSelection = []
+ if object == None:
+ return
+
+ if handler != "Forms::LayoutEditor":
+ origpage = self.page
+
+ if object._type != 'GFPage':
+ page = object.findParentOfType('GFPage')
+ if page:
+ self._setCurrentPage(page)
+ self.__drawItem(object)
+
+ self.inventoryObject(object)
+ self._setCurrentPage(origpage)
+ if object._type == 'GFBlock':
+ self.blockMap[object.name.lower()] = object
+ self._rebuildBlockCombo()
+
+
+ def onModifyObject (self, event):
+ object = event.object
+ handler = event.originator
+
+ # TODO: adjust label width to match new length...this shouldn't be here
+ if object._type == 'GFLabel':
+ mods = []
+ for field in event.new.keys():
+ value = event.new[field]
+ if field=='text':
+ if (not hasattr(object,'alignment')) or ( object.alignment ==
'left'):
+ if not hasattr(object,'Char__width') or object.Char__width !=
len(value):
+ object.Char__width=len(value)
+ # TODO: This should probably trigger a new ObjectModified event
+ event.new['Char:width'] = object.Char__width
+
+ ## self.propBar.onModifyObject(object, event)
+
+ if handler != "Forms::LayoutEditor":
+ if object._type == 'GFPage':
+ self.notebook.SetPageText(self._notebookMap[object],object.name)
+ self.notebook.SetSelection(self.notebook.GetSelection())
+ else:
+ page = object.findParentOfType('GFPage')
+ if page:
+ self._setCurrentPage(page)
+
+ if object in (self.rootObject, self.page, self.rootObject._layout) or
object in self.widgetList:
+ self.workspace.refreshPage(self.page)
+
+ if object._type == 'GFBlock' and event.old.has_key('name'):
+ del self.blockMap[event.old['name'].lower()]
+ self.blockMap[object.name.lower()] = object
+ self._rebuildBlockCombo()
+
+ self._setFeedback()
+
+
+ def onDeleteObject (self, event):
+
+ object = event.object
+ handler = event.originator
+
+ self._currentObject = None
+
+ if 1: ## handler != "Forms::LayoutEditor":
+ if object._type == 'GFPage':
+ index = self._notebookMap[object]
+ for i in range(index+1, len(self._notebookMap.keys())/2):
+ self._notebookMap[i-1] = self._notebookMap[i]
+ del self._notebookMap[int(len(self._notebookMap.keys())/2)-1]
+ del self._notebookMap[object]
+ self.notebook.DeletePage(index)
+
+ if hasattr(object, '_widgetHandler') and object._widgetHandler != None:
+ if object in self._currentSelection:
+ object._widgetHandler.setSelected(0)
+ del self._currentSelection[self._currentSelection.index(object)]
+
+ self.widgetList.remove(object)
+ ##for i in range(len(self.widgetList)):
+ ## if self.widgetList[i] == object:
+ ## self.widgetList.pop(i)
+ ## break
+
+ ## object._widget.cleanup(object)
+ object._widget._object = None
+ object._widget = None
+ object._widgetHandler.Destroy()
+ object._widgetHandler = None
+
+
+ def calcGridSpacing(self):
+ UIwxpython.initFont(self.panel)
+
+ maxWidth, maxHeight, maxDescent, maxLeading = [0,0,0,0]
+
+ checkchars = string.letters+string.digits+"-\|" + string.punctuation
+ for letter in checkchars:
+ width,height,descent,leading = self.panel.GetFullTextExtent(letter)
+ maxWidth = maxWidth > width and maxWidth or width
+ maxHeight = maxHeight > height and maxHeight or height
+ maxDescent = maxDescent > descent and maxDescent or descent
+ maxLeading = maxLeading > leading and maxLeading or leading
+
+ self.charWidth = maxWidth+maxLeading
+ self.charHeight = maxHeight+maxDescent
+
+ self.borderPercentage = (float(gConfig('borderPercentage')) / 100)
+ self.textPercentage = (float(gConfig('textPercentage')) / 100)
+
+ self.widgetWidth = int(self.charWidth * self.borderPercentage)
+ self.widgetHeight = int(self.charHeight * self.borderPercentage) + 3
+ self.textWidth = self.charWidth * self.textPercentage
+ self.textHeight = self.charHeight * self.textPercentage
+
+ self.gridWidth = self.widgetWidth
+ self.gridHeight = self.widgetHeight
+
+ self.menu_sb_space=0 # the extra spaces needed by the menu, toolbar and
statusbar
+
+ width = self.rootObject._layout.Char__width
+ height = self.rootObject._layout.Char__height
+ self.panel.SetClientSize(wxSize(int(width)*self.widgetWidth,
+ int(height)*self.widgetHeight))
+ self.panel.Refresh()
+
+
+ def drawPage(self, page):
+ self._currentSelection = []
+ self.page = page
+
+ try:
+ self.panel = self.page.__panel
+ except AttributeError:
+ self.panel = GridPane(self, self.workspace, wxPoint(10,12))
+
+ # Automatically resize workspace
+ EVT_SIZE(self.panel, self.__OnGridSize)
+
+ # We are a drop target for Drag-and-Drop
+ self.panel.SetDropTarget(DisplayDropTarget(self))
+ # self.panel.SetDropTarget(SchemaDropTarget(self))
+
+ self.page.__panel = self.panel
+ self.panelColor = self.panel.GetBackgroundColour()
+ self.panelGridColor = wxColour(order(255,self.panelColor.Red()+16)[0],
+ order(255,self.panelColor.Green()+16)[0],
+ order(255,self.panelColor.Blue()+16)[0])
+
+ page.__pointSize = UIwxpython.getPointSize()
+ self.calcGridSpacing()
+
+ page.walk(self.__drawItem)
+
+
+ EVT_CHAR(self.panel, self.keyTrap)
+ EVT_LEFT_DOWN(self.panel, self.OnLeftDown)
+ EVT_MOTION(self.panel, self.OnMotion)
+ EVT_LEFT_UP(self.panel, self.OnLeftUp)
+ EVT_RIGHT_UP(self.panel, self.OnRightUp)
+
+
+ def __drawItem(self, object):
+ if self.widgets.has_key(object._type) and \
+ (not hasattr(object, 'hidden') or not object.hidden):
+ if hasattr(object, 'name'):
+ GDebug.printMesg(7, 'Drawing item %s of type %s' % (object.name,
object._type))
+ else:
+ GDebug.printMesg(7, 'Drawing item of type %s' % (object._type))
+ object._widgetHandler = WidgetHandler(self, object)
+
+ cevent = Event('CreateUIWidget',None,
+ parent=None,
+ object=object,
+ container=self.panel,
+ textWidth=self.textWidth,
+ textHeight=self.textHeight,
+ widgetWidth=self.widgetWidth,
+ widgetHeight=self.widgetHeight,
+ interface=self,
+ eventHandler=None,
+ ui=self,
+ initialize=0)
+
+ object._widget = widget =
self.widgets[object._type].configuration['baseClass'](cevent)
+
+ # TODO: This segfaults us... yay!!!
+ widget.phaseInit(widget._buildObject())
+
+ object._widget._object = object
+ object._widgetHandler.initialize(object._widget)
+ self.widgetList.append(object)
+
+ def OnSize(self, event):
+ self.notebook.SetSize(wxSize(self.GetClientSize().x-8,
self.GetClientSize().y - 8))
+
+ def OnPageSelected(self, event):
+ p = self._notebookMap[event.GetSelection()]
+ if p != self.page:
+ self.dispatchEvent('ObjectSelected', object=p,
originator="Forms::LayoutEditor")
+ self._setCurrentPage(p)
+ self.__OnGridSize(None)
+
+ def OnLeftDown(self, event):
+ x, y = event.GetPositionTuple()
+ self.handleLeftDown(x,y)
+ event.Skip()
+
+
+ def handleLeftDown(self, x, y):
+ self.__drawing = 1
+
+ # Save starting coordinates for cross-selection box
+ self.__cx = cx = int(x / self.gridWidth)
+ self.__cy = cy = int(y / self.gridHeight)
+
+ self.setFeedback ('Col: %s Row: %s' % (cx, cy))
+
+ self.__brush = wxBrush(wxWHITE, style=wxTRANSPARENT)
+
+ self.__x = x
+ self.__y = y
+ self.__ox = None
+ self.__oy = None
+
+
+ # Used by the dragging routines to draw a selection box
+ def xorBox(self, x1, y1, x2, y2, x3=None, y3=None):
+ dc = wxClientDC(self.panel)
+ dc.SetBrush(self.__brush)
+ dc.SetPen(wxGREY_PEN)
+ dc.SetLogicalFunction(wxXOR)
+
+ if x3 != None:
+ dc.DrawRectangle(x1,y1,x3-x1,y3-y1)
+
+ dc.DrawRectangle(x1,y1,x2-x1,y2-y1)
+
+
+ def OnMotion(self, event):
+ # draw cross-selection box
+ if self.__drawing and event.LeftIsDown():
+
+ if self.__drawing == 1:
+ self.panel.SetCursor(wxCROSS_CURSOR)
+ self.__drawing = 2
+
+ x, y = event.GetPositionTuple()
+ cx = int(x / self.gridWidth)
+ cy = int(y / self.gridHeight)
+
+ cx1, cx2 = order(self.__cx, cx)
+ cy1, cy2 = order(self.__cy, cy)
+
+ self.setFeedback('Col: %s Row: %s Width: %s Height: %s'% (cx1,
cy1, cx2 - cx1 + 1, cy2 - cy1 + 1))
+
+
+
+ self.xorBox(self.__x, self.__y, x, y, self.__ox, self.__oy)
+
+ self.__ox = x
+ self.__oy = y
+
+ event.Skip()
+
+
+ def OnLeftUp(self, event):
+ x, y = event.GetPositionTuple()
+ self.handleLeftUp(x,y)
+ event.Skip()
+
+
+ def handleLeftUp(self, x, y):
+ selection = []
+
+ self.setFeedback('')
+
+ if self.__drawing and self.__ox is not None:
+
+ self.xorBox(self.__x, self.__y, self.__ox, self.__oy)
+ self.__ox = None
+ self.__oy = None
+
+ self.__drawing = 0
+
+ # Set x1,y1 to be smaller coordinates, and x2,y2 to be larger
+ x1, x2 = order(int(self.__x / self.gridWidth), int(x / self.gridWidth))
+ y1, y2 = order(int(self.__y / self.gridHeight),int(y / self.gridHeight))
+
+
+ self.panel.SetCursor(wxSTANDARD_CURSOR)
+ wxSetCursor(wxSTANDARD_CURSOR)
+
+
+ areaSelected = (x1 <> x2 or y1 <> y2)
+
+ if self.mode == 'move':
+ if areaSelected:
+ # We are selecting an area
+ self.page.walk(self.selectWidgetInArea, x1, y1, x2, y2, selection)
+ try:
+ object = selection[-1]
+ except IndexError:
+ object = self.page
+ self.dispatchEvent('ObjectSelected',
+ object = object,
+ originator = "Forms::LayoutEditor",
+ selection = selection)
+ else:
+ self.dispatchEvent('ObjectSelected',
+ object = self.page,
+ originator = "Forms::LayoutEditor")
+
+ elif self.mode == 'positioning':
+
+ if areaSelected:
+ width = x2 - x1 + 1
+ height = y2 - y1 + 1
+ else:
+ width = None
+ height = None
+
+
PrepositioningTimer(self.endPrePositioningTemplate,x1,y1,width,height).Start(100,1)
+
+
+
+ def selectWidgetInArea(self, object, x1, y1, x2, y2, selection):
+ try:
+ if x1 <= object.Char__x <= x2 and \
+ y1 <= object.Char__y <= y2:
+ if object not in selection:
+ selection.append(object)
+ except AttributeError:
+ # Not all child objects have coordinates (x,y)
+ pass
+
+
+ def OnRightUp(self, event):
+ ## self.toolbar.resetTool(self.mode)
+ self.mode = 'move'
+ self.dispatchEvent('LayoutEditor:Select')
+
+ x, y = event.GetPositionTuple()
+
+ x = int(x / self.gridWidth)
+ y = int(y / self.gridHeight)
+
+ menu = wxMenu('Layout Editor')
+ form = self._currentObject._type == 'GFForm' and self._currentObject or \
+ self._currentObject.findParentOfType('GFForm')
+ page = self._currentObject._type == 'GFPage' and self._currentObject or \
+ self._currentObject.findParentOfType('GFPage')
+ block = self._currentObject._type == 'GFBlock' and self._currentObject or
\
+ self._currentObject.findParentOfType('GFBlock')
+
+ menu.AppendMenu(wxNewId(), 'Form', PageMenu(self.instance, form, x, y))
+ if page:
+ menu.AppendMenu(wxNewId(), page.name, PageMenu(self.instance, page, x,
y))
+ if block:
+ menu.AppendMenu(wxNewId(), block.name, PageMenu(self.instance, block,
x, y))
+
+ self.panel.PopupMenu(menu, event.GetPosition())
+
+
+ def keyTrap(self, event):
+ if event.KeyCode() in (WXK_LEFT, WXK_RIGHT, WXK_UP, WXK_DOWN) and \
+ len(self._currentSelection):
+ if event.AltDown() or event.ControlDown() or event.ShiftDown():
+ # caution: event.MetaDown() is always true on some architectures
+ resize = None
+ if event.KeyCode() == WXK_LEFT:
+ resize = (-1,0)
+ if event.KeyCode() == WXK_RIGHT:
+ resize = (1,0)
+ if event.KeyCode() == WXK_UP:
+ resize = (0,-1)
+ if event.KeyCode() == WXK_DOWN:
+ resize = (0,1)
+ if resize:
+ self.dispatchEvent('BeginUndoGroup')
+ for widget in self._currentSelection:
+ widget._widgetHandler.relativeResize(*resize)
+ self.dispatchEvent('EndUndoGroup')
+ else:
+ pos = None
+ if event.KeyCode() == WXK_LEFT:
+ pos = (-1,0)
+ if event.KeyCode() == WXK_RIGHT:
+ pos = (1,0)
+ if event.KeyCode() == WXK_UP:
+ pos = (0,-1)
+ if event.KeyCode() == WXK_DOWN:
+ pos = (0,1)
+
+ if pos:
+ self.dispatchEvent('BeginUndoGroup')
+ for widget in self._currentSelection:
+ if widget._type != 'GFPage':
+ widget._widgetHandler.relativeMove(*pos)
+ self.dispatchEvent('EndUndoGroup')
+
+ elif event.KeyCode() == WXK_DELETE and \
+ len(self._currentSelection):
+ self.dispatchEvent('BeginUndoGroup')
+ for object in self._currentSelection:
+ if object._type != 'GFPage':
+ self.dispatchEvent('ObjectDeleted', object=object,
+ originator=self)
+ self.dispatchEvent('EndUndoGroup')
+ elif event.KeyCode() == WXK_TAB:
+ if event.ShiftDown():
+ object = self._currentObject
+ if hasattr(object,'_widgetHandler') and not object._type == 'GFPage':
+ i = object._parent._children.index(object)
+ lst = object._parent._children[i:] + object._parent._children[:i]
+ else:
+ lst = self.page._children[:]
+ lst.reverse()
+ for newobj in lst:
+ if hasattr(newobj,'_widgetHandler'):
+ self.instance.dispatchEvent('ObjectSelected',
+ originator=None,
+ object=newobj)
+ break
+ elif not event.ControlDown() and not event.AltDown():
+ object = self._currentObject
+ if hasattr(object,'_widgetHandler') and not object._type == 'GFPage':
+ i = object._parent._children.index(object)
+ lst = object._parent._children[i+1:] +
object._parent._children[:i+1]
+ else:
+ lst = self.page._children[:]
+ for newobj in lst:
+ if hasattr(newobj,'_widgetHandler'):
+ self.instance.dispatchEvent('ObjectSelected',
+ originator=None,
+ object=newobj)
+ break
+
+
+ def zoomIn(self, event):
+ size = UIwxpython.getPointSize()
+ if size < 72:
+ size = size + 1 # int(size * 1.05 + .5)
+ UIwxpython.setPointSize(size)
+ self.calcGridSpacing()
+ self.refreshPage(self.page)
+ self.setFeedback(_('Adjusting base point size to %spt') % size)
+ else:
+ self.setFeedback(_('Cannot adjust point size to more than 72pt'))
+
+
+ def zoomOut(self, event):
+ size = UIwxpython.getPointSize()
+ if size > 6:
+ size = size - 1 # int(size * -1.05)
+ UIwxpython.setPointSize(size)
+ self.calcGridSpacing()
+ self.refreshPage(self.page)
+ self.setFeedback(_('Adjusting base point size to %spt') % size)
+ else:
+ self.setFeedback(_('Cannot adjust point size to less than 6pt'))
+
+
+ def beginPrePositioningTemplate(self, event):
+ mode = self.mode
+ self.mode = 'positioning'
+ if mode == 'move':
+ self.dispatchEvent('Cancel:LayoutEditor:Select')
+ elif mode == 'refocus':
+ self.dispatchEvent('Cancel:LayoutEditor:FocusOrder')
+
+ ##self.panel.SetCursor(wxCROSS_CURSOR)
+ wxSetCursor(wxCROSS_CURSOR)
+ self.__wizardrunner = event.wizardrunner
+
+ def cancelPrePositioningTemplate(self, event=None):
+ if self.mode == 'prepositioning':
+ self.__wizardrunner.cancel()
+ wxSetCursor(wxSTANDARD_CURSOR)
+
+ def endPrePositioningTemplate(self, x, y, width=None, height=None):
+ self.mode = 'move'
+ self.dispatchEvent('Cancel:LayoutEditor:Prepositioning')
+ self.dispatchEvent('LayoutEditor:Select')
+ self.__wizardrunner.positioned_run(x=x, y=y, width=width, height=height)
+
+
+ def beginFocusOrder(self, event):
+ mode = self.mode
+ self.mode = 'refocus'
+ if mode == 'move':
+ event.dispatchAfter('Cancel:LayoutEditor:Select')
+ elif mode == 'positioning':
+ self.__wizardrunner.cancel()
+ # Yes, you are reading this right...
+ # I'm triggering the exact event that
+ # triggered this method. Blame it on
+ # the Tuesday night atmospheric crack
+ # levels.
+ self.dispatchEvent('LayoutEditor:FocusOrder')
+ return
+
+ self.reorderfocus.start(self.page)
+
+ def endFocusOrder(self, event):
+ self.reorderfocus.end()
+ if self.mode == 'refocus':
+ self.mode = 'move'
+ self.dispatchEvent('LayoutEditor:Select')
+
+ def beginSelectMode(self, event=None):
+ mode = self.mode
+ self.mode = 'move'
+ if mode == 'refocus':
+ self.dispatchEvent('Cancel:LayoutEditor:FocusOrder')
+ elif mode == 'positioning':
+ self.dispatchEvent('Cancel:LayoutEditor:Prepositioning')
+
+ def cancelSelectMode(self, event=None):
+ if self.mode == 'move':
+ event.dispatchAfter('LayoutEditor:Select')
+
+ def endWizard(self, event=None):
+ mode = self.mode
+ self.mode = 'move'
+ if mode == 'refocus':
+ self.dispatchEvent('Cancel:LayoutEditor:FocusOrder')
+ elif mode == 'positioning':
+ self.dispatchEvent('Cancel:LayoutEditor:Prepositioning')
+ self.dispatchEvent('LayoutEditor:Select')
+
+
+ class PrepositioningTimer(wxTimer):
+ def __init__(self, method, *args, **params):
+ self.__method = method
+ self.__args = args
+ self.__params = params
+ wxTimer.__init__(self)
+
+ def Notify(self):
+ self.__method(*self.__args, **self.__params)
+
Index: gnue-designer/src/forms/LayoutEditor/renderers/Base/Driver.py
diff -c /dev/null
gnue-designer/src/forms/LayoutEditor/renderers/Base/Driver.py:1.1.4.1
*** /dev/null Fri Aug 22 20:04:43 2003
--- gnue-designer/src/forms/LayoutEditor/renderers/Base/Driver.py Fri Aug
22 20:04:42 2003
***************
*** 0 ****
--- 1,69 ----
+ #
+ # 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.
+ #
+ # Copyright 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # renderers/Base/Driver.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+
+ from wxPython.wx import *
+
+ class BaseRenderer:
+ def __init__(self, instance):
+ self.instance = instance
+
+ StartupStatus(_('Loading Form renderers'))
+
+ self.init()
+
+ #
+ # For subclasses
+ #
+ def init(self):
+ pass
+
+
+ #
+ # Convenience
+ #
+
+ #
+ # Set the font in use and
+ # calculate the cell sizing
+ #
+ def resetFont(self):
+ self.font = font = wxSystemSettings_GetFont(wxSYS_OEM_FIXED_FONT)
+
+ # Get font extents
+ tmpBitmap = wxEmptyBitmap(100,100)
+ dc = wxMemoryDC()
+ dc.SelectObject(tmpBitmap)
+ dc.SetFont(font)
+ w, h = dc.GetTextExtent('0123456789')
+ self.cell_vert_margin = 2
+ self.cell_horiz_margin = 2
+ self.line_spacing = self.cell_vert_margin * 2
+ self.cell_height = h + self.line_spacing
+ self.cell_width = int(w/10)
+
+
Index: gnue-designer/src/forms/LayoutEditor/renderers/Base/GridPane.py
diff -c /dev/null
gnue-designer/src/forms/LayoutEditor/renderers/Base/GridPane.py:1.7.4.1
*** /dev/null Fri Aug 22 20:04:43 2003
--- gnue-designer/src/forms/LayoutEditor/renderers/Base/GridPane.py Fri Aug
22 20:04:42 2003
***************
*** 0 ****
--- 1,90 ----
+ #
+ # Copyright 2001-2003 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.
+ #
+ # FILE:
+ # GridPane.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+
+ from wxPython.wx import *
+ import sys, string
+ from gnue.designer.forms.LayoutEditor.Utils import *
+ from gnue.common.apps import GDebug
+
+
+ #
+ #
+ #
+ class GridPane(wxSashWindow):
+ def __init__(self, instance, parent, pos):
+ wxSashWindow.__init__(self, parent, -1, pos=pos,
style=wxWANTS_CHARS|wxSIMPLE_BORDER)
+ self.__showGrids = 1
+ self.__instance = instance
+ EVT_PAINT(self, self.OnPaint)
+
+ # TODO: Have the sash events resize the form
+ self.SetSashVisible(wxSASH_RIGHT,1)
+ self.SetSashVisible(wxSASH_BOTTOM,1)
+
+ EVT_SASH_DRAGGED(self, self.GetId(), self.SashChanged)
+
+ def OnPaint(self, event):
+ if self.__showGrids:
+ dc = wxPaintDC(self)
+ dc.BeginDrawing()
+ w, h = self.GetSizeTuple()
+ dc.SetPen(wxPen(self.__instance.workspace.panelGridColor))
+ for x in range(self.__instance.workspace.widgetWidth,w-3,
self.__instance.workspace.widgetWidth):
+ dc.DrawLine(x,0,x,h-1)
+
+ for y in
range(self.__instance.workspace.widgetHeight,h-2,self.__instance.workspace.widgetHeight):
+ dc.DrawLine(0,y,w-1,y)
+ dc.EndDrawing()
+ event.Skip()
+
+ def SashChanged(self, event):
+ w = event.GetDragRect().width
+ h = event.GetDragRect().height
+
+ neww = int(w/float(self.__instance.workspace.widgetWidth)+.5)
+ newh = int(h/float(self.__instance.workspace.widgetHeight)+.5)
+
+ layout = self.__instance.instance.rootObject._layout
+
+ oldvars = {}
+ newvars = {}
+
+ if neww != layout.Char__width:
+ oldvars['Char:width'] = layout.Char__width
+ newvars['Char:width'] = neww
+ layout.Char__width = neww
+ if newh != layout.Char__height:
+ oldvars['Char:height'] = layout.Char__height
+ newvars['Char:height'] = newh
+ layout.Char__height = newh
+
+ if oldvars:
+ self.__instance.instance.dispatchEvent('ObjectModified', object=layout,
+ originator="Forms::GridPane",
+ old=oldvars,
+ new=newvars)
+
Index: gnue-designer/src/forms/LayoutEditor/renderers/curses/Driver.py
diff -c /dev/null
gnue-designer/src/forms/LayoutEditor/renderers/curses/Driver.py:1.1.4.1
*** /dev/null Fri Aug 22 20:04:43 2003
--- gnue-designer/src/forms/LayoutEditor/renderers/curses/Driver.py Fri Aug
22 20:04:42 2003
***************
*** 0 ****
--- 1,230 ----
+ #
+ # 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.
+ #
+ # Copyright 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # curses/Driver.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+
+ from wxPython.wx import *
+ from gnue.designer.forms.LayoutEditor.renderers.Base import *
+ import string
+
+ class Renderer(BaseRenderer):
+
+ ##########
+ #
+ # Public methods
+ #
+
+ def init(self):
+ self.map = {
+ 'GFScrollbar': self.scrollbar,
+ 'GFEntry': self.entry,
+ 'GFButton': self.button,
+ 'GFImage': self.image,
+ 'GFLabel': self.label,
+ 'GFBox': self.box,
+
+ self.resetFont()
+
+ def removeWidget(self, object):
+ # We don't need to do anything special
+ # if a widget is removed
+ return
+
+ def redrawWidget(self, object):
+ # We don't need to do anything special,
+ # other than recreate the bitmap, if a
+ # widget is redrawn/updated
+ return self.addWidget(object)
+
+ def addWidget(self, object):
+ try:
+ func = self.map[object._type]
+ except:
+ func = self.unknown
+
+ return func(object)
+
+
+
+ ##########
+ #
+ # Internal methods
+ #
+
+
+ #
+ # Known objects
+ # Return a wxBitmap
+ #
+ def entry(self, object):
+ return self.simpleTextObject(object, 10, 1, COLOR_TEXTBOX, "", 0)
+
+ def button(self, object):
+ # Default the width to the length of
+ # the label if width hasn't been set.
+ try: width = object.Char__width
+ except: width = len(object.label)
+
+ # Create a label formatted as <Button Name>
+ # and pad it to take up the width
+ label = string.center('<' + object.label[:width-2] + '>', width)
+
+ # Use our handy-dandy bitmap creator to do the rest
+ return self.simpleTextObject(object, width, 1, COLOR_BUTTON, text, 0)
+
+ def label(self, object):
+
+ # Default the width to the length of
+ # the label if width hasn't been set.
+ try: width = object.Char__width
+ except: width = len(object.label)
+
+ # Get the label alignment, if set
+ try: alignment = object.alignment
+ except: alignment = 'left'
+
+ # Align the text
+ text = aligners[alignment](object.label[:width],width)
+
+ # And use our handy-dandy bitmap creator to do the rest
+ return self.simpleTextObject(object, width, 1, COLOR_LABEL, object.label,
1)
+
+ def scrollbar(self, object):
+ return self.unknown(object)
+
+ def box(self, object):
+ return self.unknown(object)
+
+ def image(self, object):
+ # We don't support this,
+ # so create an "unknown" object
+ return self.unknown(object)
+
+
+ #
+ # Unknown/unsupported object
+ # Return a wxBitmap with
+ # cross-hatching
+ #
+ def unknown(self, object):
+ # TODO: something better
+ return self.simpleTextObject(object, 10, 1, COLOR_BACKGROUND, "", 0)
+
+
+ #
+ # Encapsulate the creation of widgets that are nothing more than
+ # a one-line display of text (w/appropriate colors)
+ #
+ def simpleTextObject(object, text, defw, defh, colors, transparent=0):
+ dc, bitmap = self.createBitmap(object, defw, defh)
+ self.writeText(dc, 0, 0, colors, text, transparent)
+
+
+ #
+ # Create a bitmap object
+ # using the char-based width/height
+ #
+ def createBitmap(self, object, defw=10, defh=1):
+ # Get the bitmap width and height
+ try:
+ h = object.Char__height * self.heightAdjustment
+ except:
+ h = defw
+
+ try:
+ w = object.Char__width * self.heightAdjustment
+ except:
+ w = defw
+
+ dc = wxMemoryDC()
+ bitmap = wxEmptyBitmap(w, h)
+ dc.SelectObject(bitmap)
+ dc.SetFont(self.font)
+ return (dc, bitmap)
+
+
+
+ #
+ # Draw text onto the bitmap
+ # Supports background coloring
+ # and multiline-text
+ #
+ def writeText(self, dc, x, y, colors, text, transparent=0):
+
+ fgcolor, bgcolor = colors
+ if not transparent:
+ dc.SetBackground(wxBrush(bgcolor))
+ dc.Clear()
+ else:
+ dc.SetBackground(wxTRANSPARENT_BRUSH)
+
+ dc.SetTextForeground(fgcolor)
+
+ ox = x * self.cell_width + self.cell_horiz_margin
+ oy = x * self.cell_height + self.cell_vert_margin
+
+
+ for line in text.split('\n'):
+ dc.DrawText(line, ox, oy)
+ oy += self.cell_height
+
+
+
+ WHITE = wxWHITE
+ BLUE = wxBLUE
+ CYAN = wxCYAN
+ BLACK = wxBLACK
+ RED = wxRED
+
+
+ # These names were copied over
+ # from gnue.common.cursing;
+ # not all are used here.
+ COLOR_BACKGROUND=(WHITE,BLUE)
+ COLOR_TITLEBAR=(WHITE,BLUE)
+ COLOR_TEXTBOX_FOCUS=(BLACK,CYAN)
+ COLOR_TEXTBOX=(BLUE,WHITE)
+ COLOR_MENUBAR=(BLACK,WHITE)
+ COLOR_MENUBAR_FOCUS=(BLUE,WHITE)
+ COLOR_LABEL=(BLACK,WHITE)
+ COLOR_STATUSBAR=(BLACK,WHITE)
+ COLOR_STATUSBAR_FIELD=(BLACK,WHITE)
+ COLOR_DIALOG=(BLACK,WHITE)
+ COLOR_DIALOG_TITLE=(BLACK,WHITE)
+ COLOR_BUTTON=(BLUE,WHITE)
+ COLOR_BUTTON_FOCUS=(WHITE,CYAN)
+ COLOR_SCROLL_BUTTON=(BLACK,WHITE)
+ COLOR_SCROLL_BUTTON_FOCUS=(CYAN,WHITE)
+ COLOR_SCROLL_BACKGROUND=(BLUE,WHITE)
+ COLOR_SCROLL_SLIDER=(WHITE,BLUE)
+ COLOR_SCROLL_SLIDER_FOCUS=(BLACK,CYAN)
+ COLOR_DROPSHADOW=(WHITE,BLACK)
+
+ # Convenience mapper for <label>.alignment => python method
+ aligners = {'left':string.ljust,
+ 'right':string.rjust,
+ 'center':string.center}
+
Index: gnue-designer/src/forms/LayoutEditor/renderers/native/Driver.py
diff -c /dev/null
gnue-designer/src/forms/LayoutEditor/renderers/native/Driver.py:1.1.4.1
*** /dev/null Fri Aug 22 20:04:43 2003
--- gnue-designer/src/forms/LayoutEditor/renderers/native/Driver.py Fri Aug
22 20:04:42 2003
***************
*** 0 ****
--- 1,114 ----
+ #
+ # 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.
+ #
+ # Copyright 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # native/Driver.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+
+ from wxPython.wx import *
+ from gnue.designer.forms.LayoutEditor.renderers.Base import *
+ from gnue.forms.uidrivers.wx import UIdriver as UIwxpython
+ from gnue.common.events import Event
+ from WidgetHandler import WidgetHandler
+
+ class Renderer(BaseRenderer):
+
+ ##########
+ #
+ # Public methods
+ #
+
+ def init(self):
+ # Create our own WX GFUserInterface instance
+ self.uidriver = uidriver = UIwxpython.GFUserInterface(self.instance, 0)
+
+ # Create a list of all UI widgets
+ self.widgets = {}
+ self.widgets.update(uidriver._supportedWidgets)
+
+ # But we don't want a page to act like normal objects...
+ # we have special plans for it (bwahahaha)
+ del self.widgets['GFPage']
+
+ self.widgetList = []
+
+ self.resetFont()
+
+
+ def removeWidget(self, object):
+ # We don't need to do anything special
+ # if a widget is removed
+ try:
+ self.widgetList.remove(object)
+ except:
+ pass
+
+
+ def redrawWidget(self, object):
+ # We don't need to do anything special,
+ # other than recreate the bitmap, if a
+ # widget is redrawn/updated
+ return self.addWidget(object)
+
+
+ def addWidget(self, object):
+ if self.widgets.has_key(object._type) and \
+ (not hasattr(object, 'hidden') or not object.hidden):
+ if hasattr(object, 'name'):
+ GDebug.printMesg(7, 'Drawing item %s of type %s' % (object.name,
object._type))
+ else:
+ GDebug.printMesg(7, 'Drawing item of type %s' % (object._type))
+ object._widgetHandler = WidgetHandler(self.layouteditor, object)
+
+ cevent = Event('CreateUIWidget',None,
+ parent=None,
+ object=object,
+ container=self.layouteditor.workspace.panel,
+ textWidth=self.textWidth,
+ textHeight=self.textHeight,
+ widgetWidth=self.widgetWidth,
+ widgetHeight=self.widgetHeight,
+ interface=self,
+ eventHandler=None,
+ ui=self,
+ initialize=0)
+
+ object._widget = widget =
self.widgets[object._type].configuration['baseClass'](cevent)
+
+ # TODO: This segfaults us... yay!!! (is this fixed???)
+ widget.phaseInit(widget._buildObject())
+
+ object._widget._object = object
+ object._widgetHandler.initialize(object._widget)
+ self.widgetList.append(object)
+
+
+
+
+ ##########
+ #
+ # Internal methods
+ #
+
+
Index: gnue-designer/src/forms/LayoutEditor/renderers/native/WidgetHandler.py
diff -c /dev/null
gnue-designer/src/forms/LayoutEditor/renderers/native/WidgetHandler.py:1.15.4.1
*** /dev/null Fri Aug 22 20:04:43 2003
--- gnue-designer/src/forms/LayoutEditor/renderers/native/WidgetHandler.py
Fri Aug 22 20:04:42 2003
***************
*** 0 ****
--- 1,375 ----
+ #
+ # 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.
+ #
+ # Copyright 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # WidgetHandler.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ # (TODO) This needs to go bye-bye
+
+ from wxPython.wx import *
+ import sys, string
+ from gnue.common.apps import GDebug
+ import cPickle
+
+ # LayoutEditor support files
+ from gnue.designer.forms.LayoutEditor.WidgetHighlighter import
WidgetHighlighter
+ from gnue.designer.forms.LayoutEditor.PopupEditor import PopupEditor
+ from gnue.designer.forms.LayoutEditor.Utils import *
+
+ #
+ #
+ #
+ class WidgetHandler(wxEvtHandler):
+ def __init__(self, instance, object):
+ wxEvtHandler.__init__(self)
+ self.editor = instance
+ self.object = object
+ self.hasFocus = 0
+ self.highlightBox = WidgetHighlighter(self.editor.panel)
+ self._iMoved = 0
+ self._alreadySelected = 0
+ self._popup_editor = None
+
+ def initialize(self, widget):
+ self.widget = widget.widgets[0]
+ self.mainWidget = widget
+ self.selected = 0
+
+ self.recalcBoundaries()
+
+ for widget in self.mainWidget.widgets:
+ widget.SetCursor (wxSTANDARD_CURSOR)
+
+ # try:
+ # widget.Enable(0)
+ # except:
+ # pass
+
+ try:
+ widget.SetEditable(0)
+ except:
+ pass
+
+ self.setAllChildren(EVT_KEY_UP, widget, self.editor.keyTrap)
+ self.setAllChildren(EVT_SET_FOCUS, widget, self.focusGainedTrap)
+ self.setAllChildren(EVT_KILL_FOCUS, widget, self.focusLostTrap)
+ self.setAllChildren(EVT_LEFT_UP, widget, self.OnLeftUp)
+ self.setAllChildren(EVT_LEFT_DOWN, widget, self.OnLeftDown)
+ self.setAllChildren(EVT_RIGHT_DOWN, widget, self.OnRightDown)
+ self.setAllChildren(EVT_RIGHT_UP, widget, self.OnRightUp)
+ self.setAllChildren(EVT_MOTION, widget, self.OnMotion)
+ self.setAllChildren(EVT_LEFT_DCLICK, widget, self.onLeftDClick)
+ self.setAllChildren(EVT_KEY_UP, self.highlightBox, self.editor.keyTrap)
+ self.setAllChildren(EVT_SET_FOCUS, self.highlightBox,
self.focusGainedTrap)
+ self.setAllChildren(EVT_KILL_FOCUS, self.highlightBox, self.focusLostTrap)
+ self.setAllChildren(EVT_LEFT_UP, self.highlightBox, self.OnLeftUp)
+ self.setAllChildren(EVT_LEFT_DOWN, self.highlightBox, self.OnLeftDown)
+ self.setAllChildren(EVT_RIGHT_UP, self.highlightBox, self.OnRightUp)
+ self.setAllChildren(EVT_MOTION, self.highlightBox, self.OnMotion)
+
+ self.widget.Refresh()
+
+ def recalcBoundaries(self):
+ x1,y1,x2,y2 = (9999999,9999999,0,0)
+
+ for widget in self.mainWidget.widgets:
+ tx, ty = widget.GetPositionTuple()
+ tw, th = widget.GetSizeTuple()
+ self.editor.positionMappings[widget] = [tx,ty,tx+tw-1,ty+tw-1,self]
+ if tx < x1:
+ x1 = tx
+ if ty < y1:
+ y1 = ty
+ if tw + tx > x2:
+ x2 = tw + tx
+ if th + ty > y2:
+ y2 = th + ty
+
+ self.highlightBox.setBoundary(x1-2,y1-2,x2+2,y2+2)
+ for widget in self.mainWidget.widgets:
+ widget.Refresh()
+
+
+ def setSelected(self, selected, focused=1):
+ self.selected = selected
+ self.focused = focused
+ self.highlightBox.setSelected(selected, focused)
+
+
+ def setAllChildren(self, event, widget, trap):
+ try:
+ event(widget, trap)
+ except:
+ pass
+ for child in widget.GetChildren():
+ self.setAllChildren(event, child, trap)
+
+ def focusGainedTrap(self, event):
+ self.editor.panel.SetFocus()
+ pass
+ # event.Skip()
+
+ def focusLostTrap(self, event):
+ event.Skip()
+
+
+ def beginDragDrop(self, event):
+
+ # Drag and drop TODO: This needs changed to pull all selected widgets
+
+ object = self.object
+
+ x,y = event.GetPositionTuple()
+
+ data = [ { "Type" : "selectedWidgets",
+ "Attributes": {
+ 'startingX': object.Char__x + int(x/self.editor.gridWidth),
+ 'startingY': object.Char__y +
int(y/self.editor.gridHeight),
+ }
+ }]
+ # "name": dname,
+ # "table": object.name,
+ # "database": self.connectionName } }
+ #
+ #
+ do = wxCustomDataObject(wxCustomDataFormat("application/x-gnue-designer"))
+ do.SetData(cPickle.dumps(data,1))
+
+ ## icon = FeedbackBitmap(10,10).icon()
+ dropSource = MoveDropSource(self, self.editor)
+ dropSource.SetData(do)
+ result = dropSource.DoDragDrop(true)
+ event.Skip()
+
+
+ def OnLeftDown(self, event):
+
+ if self.editor.mode == 'move':
+
+ self.mouseStartX, self.mouseStartY = event.GetPositionTuple()
+ self._iMoved = 0
+
+ if event.ShiftDown():
+ selections = self.editor._currentSelection[:]
+ else:
+ selections = []
+
+ if self.object in selections:
+ if event.ShiftDown():
+ del selections[selections.index(self.object)]
+ else:
+ selections.append(self.object)
+
+ self.editor._instance.dispatchEvent('ObjectSelected',object=self.object,
+ originator="Forms::LayoutEditor",
+ selection=selections)
+ else:
+ xo, yo = self.widget.GetPosition()
+ x, y = event.GetPositionTuple()
+ self.editor.handleLeftDown(x+xo,y+yo)
+
+ event.Skip()
+
+
+ def OnLeftUp(self, event):
+ if self.editor.mode == 'move':
+ if self._iMoved:
+ self._iMoved = 0
+ else:
+ xo, yo = self.widget.GetPosition()
+ x, y = event.GetPositionTuple()
+ self.editor.handleLeftUp(x+xo,y+yo)
+
+ event.Skip()
+
+
+ def OnMotion(self, event):
+
+ if not self._iMoved and event.LeftIsDown():
+ self._iMoved = 1
+ self.beginDragDrop(event)
+
+ event.Skip()
+
+
+ def OnRightDown(self, event):
+ event.Skip()
+
+
+ def OnRightUp(self, event):
+ if self.editor.mode == 'move':
+ pt = event.GetPositionTuple()
+ self.editor.dispatchEvent('ObjectSelected',object=self.object,
originator=None)
+ wxPyTypeCast(event.GetEventObject(),'wxWindow') \
+ .PopupMenu(self.object._popupMenu, pt)
+ event.Skip()
+
+
+ def _endPopupEditor(self, success, value=""):
+ if success:
+
+ try:
+ oldVals = {self.__popupAttr:self.object.__dict__[self.__popupAttr]}
+ except KeyError:
+ oldVals = {self.__popupAttr:None}
+ newVals = {self.__popupAttr: value}
+ self.object.__dict__.update(newVals)
+ self.editor.dispatchEvent('ObjectModified', object=self.object,
+ originator="Forms::LayoutEditor",
+ old=oldVals,
+ new=newVals)
+
+ self._popup_editor.Destroy()
+ self._popup_editor = None
+ self.widget.SetLabel(value or "<Unset>")
+ if self.object._type == 'GFLabel':
+ width = len(value) or 10
+ self.widget.SetSize((width * self.editor.gridWidth,
+ self.widget.GetSize().height))
+ self.recalcBoundaries()
+ self.setSelected(self.selected)
+
+
+ def onLeftDClick(self, event):
+
+ if self.editor.mode == 'move':
+ if self.object._type in ('GFBox','GFLabel'):
+ # Create a popup text editor for the labels
+ if self.object._type == 'GFBox':
+ self.__popupAttr = 'label'
+ x = self.widget.GetPosition().x + (self.editor.gridWidth/2)
+ width = (self.object.Char__width - 2) * self.editor.gridWidth
+ else:
+ self.__popupAttr = 'text'
+ x = self.widget.GetPosition().x
+ width = self.widget.GetSize().width + self.editor.gridWidth
+
+ self._popup_editor = PopupEditor(self.editor.workspace,
+ self._endPopupEditor,
+ x + self.editor.panel.GetPosition().x,
+ self.widget.GetPosition().y + self.editor.panel.GetPosition().y,
+ width,
+ self.editor.gridHeight,
+ self.object.__dict__[self.__popupAttr])
+
+ self._popup_editor.SetFocus()
+
+ else:
+ # Signal the Properties dialog
+ self.editor._instance.dispatchEvent('Show:Tool:objectProperties')
+
+
+ #
+ # Resize the current widget. dx and dy are incremental
+ # resize units. (e.g, (-1,0) means make the widget one
+ # unit smaller than it currently is.
+ #
+ def relativeResize(self, dx, dy):
+ if not (dx or dy):
+ return 0
+
+ nx = dx * self.editor.gridWidth
+ ny = dy * self.editor.gridHeight
+
+ try:
+ self.object.Char__height
+ except:
+ self.object.Char__height = 1
+
+ if (self.object.Char__width + dx < 0 or self.object.Char__height + dy <
0):
+ return 0
+ else:
+ for widget in self.mainWidget.widgets:
+ x,y = widget.GetSizeTuple()
+ widget.SetSize(wxSize(x + nx,y + ny))
+
+ oldVals = {}
+ newVals = {}
+ if dx:
+ oldVals['Char:width'] = self.object.Char__width
+ self.object.Char__width = self.object.Char__width + dx
+ newVals['Char:width'] = self.object.Char__width
+ if dy:
+ oldVals['Char:height'] = self.object.Char__height
+ self.object.Char__height = self.object.Char__height + dy
+ newVals['Char:height'] = self.object.Char__height
+
+ self.editor.dispatchEvent('ObjectModified', object=self.object,
+ originator="Forms::LayoutEditor",
+ old=oldVals,
+ new=newVals)
+
+ self.recalcBoundaries()
+
+
+ #
+ # Move the current widget. dx and dy are increments.
+ # (e.g., (-1,-2) means move the object up one unit
+ # and left two units.
+ #
+ def relativeMove(self, dx, dy):
+ if not (dx or dy):
+ return 0
+
+ nx = dx * self.editor.gridWidth
+ ny = dy * self.editor.gridHeight
+
+ if (self.object.Char__x + dx < 0 or self.object.Char__y + dy < 0):
+ return 0
+ else:
+ for widget in self.mainWidget.widgets:
+ x,y = widget.GetPositionTuple()
+ widget.SetPosition(wxPoint(x + nx,y + ny))
+ oldVals = {}
+ newVals = {}
+ if dx:
+ oldVals['Char:x'] = self.object.Char__x
+ self.object.Char__x += dx
+ newVals['Char:x'] = self.object.Char__x
+ if dy:
+ oldVals['Char:y'] = self.object.Char__y
+ self.object.Char__y += dy
+ newVals['Char:y'] = self.object.Char__y
+
+ self.editor.dispatchEvent('ObjectModified', object=self.object,
+ originator="Forms::LayoutEditor",
+ old=oldVals,
+ new=newVals)
+
+ self.recalcBoundaries()
+
+ #
+ # Recursively destroy this widget set
+ #
+ def Destroy(self):
+
+ # TODO: Why the fsck can't I Destroy() this thing!?!??!?
+ self.widget.Show(0)
+
+ self.editor = None
+ self.object = None
+ self.highlightBox.Destroy()
+ self.highlightBox = None
+ self._popup_editor = None
+ self.widget = None
+ self.mainWidget = None
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- CVSROOT: /cvsroot/gnue,
Jason Cater <=