16 |
# write to the Free Software Foundation, Inc., 59 Temple Place |
# write to the Free Software Foundation, Inc., 59 Temple Place |
17 |
# - Suite 330, Boston, MA 02111-1307, USA. |
# - Suite 330, Boston, MA 02111-1307, USA. |
18 |
# |
# |
19 |
# Copyright 2000-2002 Free Software Foundation |
# Copyright 2000-2003 Free Software Foundation |
20 |
# |
# |
21 |
# FILE: |
# FILE: |
22 |
# UIwxpython.py |
# UIwxpython.py |
25 |
# A wxPython based user interface driver for GNUe forms. |
# A wxPython based user interface driver for GNUe forms. |
26 |
# |
# |
27 |
# NOTES: |
# NOTES: |
|
# TODO: why does UIhelper not inherit from UIwidget? |
|
28 |
# |
# |
29 |
|
import sys |
30 |
|
import string |
31 |
|
|
32 |
|
from wxPython import __version__ as WXVERSION |
33 |
from wxPython.wx import * |
from wxPython.wx import * |
34 |
from wxPython.lib.splashscreen import SplashScreen |
|
|
from gnue.forms.GFForm import * |
|
35 |
from gnue.common import events |
from gnue.common import events |
36 |
from gnue.forms import GFKeyMapper |
from gnue.common import GDebug |
37 |
|
from gnue.common import GConfig |
38 |
|
from gnue.common.TextUtils import lineWrap |
39 |
|
|
40 |
|
from gnue.forms import VERSION |
41 |
|
from gnue.forms.GFForm import * |
42 |
from gnue.forms.uidrivers._base.UIdriver import * |
from gnue.forms.uidrivers._base.UIdriver import * |
43 |
from gnue.forms.uidrivers._base.UIWidget import * |
from gnue.forms.uidrivers._base.UIWidget import * |
44 |
|
|
45 |
import os |
from gnue.forms.uidrivers.wx.GFwxApp import * |
46 |
import sys |
from gnue.forms.uidrivers.wx.UIWXSplashScreen import * |
47 |
import string |
#from UIWidgets import * |
48 |
from gnue.forms import VERSION |
from common import * |
49 |
from gnue.common import GDebug, GLoginHandler |
|
|
from gnue.common import GConfig |
|
|
from gnue.common.TextUtils import lineWrap |
|
50 |
|
|
|
_LOOPTRAP = 0 |
|
51 |
_PROMPTFORRECORD = None |
_PROMPTFORRECORD = None |
52 |
_charWidth = 0 |
_charWidth = 0 |
53 |
_charHeight = 0 |
_charHeight = 0 |
57 |
|
|
58 |
_disabledColour = wxLIGHT_GREY |
_disabledColour = wxLIGHT_GREY |
59 |
|
|
|
# Finishing creation of dictionary for language font encodings |
|
60 |
|
|
61 |
|
# Shortcut |
62 |
|
images_dir = GConfig.getInstalledBase('forms_images','common_images') + '/' |
63 |
|
|
64 |
|
# Finishing creation of dictionary for language font encodings |
65 |
encodings = { |
encodings = { |
66 |
'iso8859-1': wxFONTENCODING_ISO8859_1, |
'iso8859-1': wxFONTENCODING_ISO8859_1, |
67 |
'iso8859-2': wxFONTENCODING_ISO8859_2, |
'iso8859-2': wxFONTENCODING_ISO8859_2, |
90 |
eo = event.GetEventObject() |
eo = event.GetEventObject() |
91 |
return wxPyTypeCast(eo, 'wxWindow') |
return wxPyTypeCast(eo, 'wxWindow') |
92 |
|
|
|
## |
|
|
## Only create one instance of wxApp |
|
|
## Use getWxApp() to get or create the |
|
|
## single instance |
|
|
## |
|
|
## TODO: It seems this could all be folded |
|
|
## TODO: into an __init__ inside GFwxApp |
|
|
## |
|
|
__wxApp = None |
|
|
|
|
|
def getWxApp(): |
|
|
global __wxApp |
|
|
|
|
|
if not __wxApp: |
|
|
GDebug.printMesg(7,"WxApp initializing") |
|
|
__wxApp = GFwxApp(0) |
|
|
return __wxApp |
|
|
|
|
|
|
|
|
class GFwxApp(wxApp): |
|
|
_mainLoop= None |
|
|
|
|
|
def OnInit(self): |
|
|
GDebug.printMesg(7,"WxApp initializing") |
|
|
wxInitAllImageHandlers() |
|
|
return true |
|
|
|
|
|
def MainLoop (self): |
|
|
# just to launch one wx's mainloop |
|
|
# otherwise, the app does not finishes cleanly when several windows are open |
|
|
# 'cause the first mainloop gets all the events |
|
|
# and the others just sit and wait for something to happen |
|
|
if self._mainLoop==None: |
|
|
self._mainLoop= 1 |
|
|
wxApp.MainLoop (self) |
|
|
|
|
93 |
|
|
94 |
# |
# |
95 |
# Little global helper routine to set font according to options |
# Little global helper routine to set font according to options |
99 |
def initFont(widget, affectsLayout=1): |
def initFont(widget, affectsLayout=1): |
100 |
if int(gConfigForms('fixedWidthFont')): |
if int(gConfigForms('fixedWidthFont')): |
101 |
widget.SetFont(wxFont(int(gConfigForms('pointSize')),wxMODERN,wxNORMAL,\ |
widget.SetFont(wxFont(int(gConfigForms('pointSize')),wxMODERN,wxNORMAL,\ |
102 |
wxNORMAL,FALSE,'',encodings[gConfigForms('formFontEncoding')])) |
wxNORMAL,FALSE,'',encodings[gConfig('textEncoding')])) |
103 |
|
|
104 |
# |
# |
105 |
# GFUserInterface |
# GFUserInterface |
109 |
# |
# |
110 |
class GFUserInterface(GFUserInterfaceBase): |
class GFUserInterface(GFUserInterfaceBase): |
111 |
def __init__(self, eventController, disableSplash = None): |
def __init__(self, eventController, disableSplash = None): |
112 |
|
GFUserInterfaceBase.__init__(self,eventController) |
113 |
self._WIDGETS = WIDGETS |
|
|
|
|
114 |
self._DIALOGS = {'about' :UIAbout, |
self._DIALOGS = {'about' :UIAbout, |
115 |
'messageBox' :UIMessageBox, |
'messageBox' :UIMessageBox, |
|
'genericBox' :UIGenericBox, |
|
116 |
} |
} |
117 |
|
|
118 |
self._aboutDialog = UIAbout |
# On only this driver these are defined outside the GFUserInterface |
119 |
self._messageDialog = UIMessageBox |
# class at the bottom of this file. This is because GNUe Designer |
120 |
|
# is written using wx and pulls these values from this driver |
121 |
|
self._WIDGETS = WIDGETS |
122 |
|
|
123 |
|
################################################################ |
124 |
|
# WX Specifics |
125 |
|
################################################################ |
126 |
self._wxapp = getWxApp() |
self._wxapp = getWxApp() |
|
self._disableSplash = disableSplash |
|
|
GFUserInterfaceBase.__init__(self,eventController) |
|
|
|
|
|
global _PROMPTFORRECORD |
|
|
_PROMPTFORRECORD = self.promptForRecordNumber |
|
|
|
|
|
self.forms = {} |
|
|
self.init() |
|
|
|
|
|
# |
|
|
# init |
|
|
# |
|
|
# Routine called by wxWindows when wxApp instance is created |
|
|
# It is used the build the basic UI |
|
|
# |
|
|
def init(self): |
|
127 |
|
|
128 |
# |
# |
129 |
# SplashScreen |
# SplashScreen |
130 |
# |
# |
131 |
if not self._disableSplash: |
if not disableSplash: |
132 |
self.splash = SplashScreen(None,bitmapfile=images_dir+gConfigForms('splashScreenPNG'), |
self.splash = UIWXSplashScreen() |
|
duration = 3000, callback=self.onCloseSplash, |
|
|
style=wxSIMPLE_BORDER|wxCENTRE_ON_SCREEN ) |
|
|
swidth,sheight = self.splash.GetSizeTuple() |
|
|
|
|
|
# Make the splash text print white |
|
|
self.splash.SetForegroundColour(wxColour(0xFF, 0xFF, 0xFF)) |
|
|
self.splash.SetFont(wxFont(20,wxSWISS,wxNORMAL,wxBOLD)) |
|
|
|
|
|
text = _("GNU Enterprise Forms") |
|
|
twidth,theight = self.splash.GetTextExtent(text) |
|
|
wxStaticText(parent=self.splash, id=-1, label=str(text), |
|
|
size=wxSize(swidth,theight),pos=wxPoint(1,1),style=wxALIGN_CENTRE) |
|
|
|
|
|
self.splash.SetFont(wxFont(10,wxSWISS,wxNORMAL,wxBOLD)) |
|
|
|
|
|
text = _("Version %s") % VERSION |
|
|
twidth,theight = self.splash.GetTextExtent(text) |
|
|
wxStaticText(parent=self.splash, id=-1, label=str(text), |
|
|
size=wxSize(swidth,theight), pos=wxPoint(1,25),style=wxALIGN_CENTRE) |
|
|
|
|
|
text = "(c)2000-2002 Free Software Foundation" |
|
|
twidth,theight = self.splash.GetTextExtent(text) |
|
|
wxStaticText(self.splash, -1, str(text), |
|
|
wxPoint(1,50),wxSize(swidth,theight),wxALIGN_CENTRE) |
|
|
|
|
|
text = _("Protected by GNU General Public Licence 2.0") |
|
|
wxStaticText(self.splash, -1, str(text), |
|
|
wxPoint(1,sheight-(theight+10)),wxSize(swidth-5,theight),wxALIGN_RIGHT) |
|
133 |
|
|
134 |
self.splash.CenterOnScreen() |
self.wxSpecificInit(disableSplash) |
135 |
self.splash.Show(true) |
|
136 |
|
def wxSpecificInit(self, disableSplash): |
137 |
|
global _PROMPTFORRECORD |
138 |
|
_PROMPTFORRECORD = self.promptForRecordNumber |
139 |
|
|
140 |
# |
# |
141 |
# Create the main window |
# Create the main window |
156 |
maxDescent = max(maxDescent,descent) |
maxDescent = max(maxDescent,descent) |
157 |
maxLeading = max(maxLeading,leading) |
maxLeading = max(maxLeading,leading) |
158 |
|
|
|
self.charWidth = int(maxWidth+maxLeading) |
|
|
self.charHeight = int(maxHeight+maxDescent) |
|
|
|
|
|
self.widgetWidth = self.charWidth # The pixel width of a 1 char widget (for things like buttons) |
|
|
self.widgetHeight = self.charHeight + 3 # The pixel height of a 1 char widget (for things like buttons) |
|
|
self.textWidth = self.charWidth # The pixel width of text inside a widget |
|
|
self.textHeight = self.charHeight # The pixel height of text inside a widget |
|
|
|
|
159 |
global _charWidth, _charHeight |
global _charWidth, _charHeight |
160 |
_charWidth = self.charWidth # Used by the mouse handler to compute char offset into widget |
_charWidth = int(maxWidth+maxLeading) # Used by the mouse handler to compute char offset into widget |
161 |
_charHeight = self.charHeight # |
_charHeight = int(maxHeight+maxDescent) # |
162 |
|
self.textWidth = _charWidth # The pixel width of text inside a widget |
163 |
|
self.textHeight = _charHeight # The pixel height of text inside a widget |
164 |
|
self.widgetWidth = _charWidth # The pixel width of a 1 char widget (for things like buttons) |
165 |
|
self.widgetHeight = _charHeight + 3 # The pixel height of a 1 char widget (for things like buttons) |
166 |
|
|
167 |
self.menu_sb_space=4 # the extra spaces needed by the menu, toolbar and statusbar |
self.menu_sb_space=4 # the extra spaces needed by the menu, toolbar and statusbar |
168 |
|
|
171 |
self.statusBar.SetStatusWidths([-1,50,50,75,75]) |
self.statusBar.SetStatusWidths([-1,50,50,75,75]) |
172 |
initFont(self.statusBar,0) |
initFont(self.statusBar,0) |
173 |
|
|
174 |
|
self._scrollWindow = self.mainWindow.panel = wxScrolledWindow(self.mainWindow,-1, wxDefaultPosition,self.mainWindow.GetClientSize()) |
175 |
|
|
176 |
# This will be a dict of the form { 'requestROLLBACK': 1001 } |
setDisabledColour(self.mainWindow.GetBackgroundColour()) |
|
# where 1001 is the wxId associated with requestROLLBACK. |
|
|
self.__eventActionMapping = {} |
|
|
|
|
|
|
|
|
# add actions |
|
|
self.__addAction ('requestCOMMIT') |
|
|
self.__addAction ('requestROLLBACK') |
|
|
self.__addAction ('requestPRINTOUT') |
|
|
self.__addAction (self.menuExitEvent, '_exit_') |
|
|
self.__addAction ('requestCUT') |
|
|
self.__addAction ('requestCOPY') |
|
|
self.__addAction ('requestPASTE') |
|
|
self.__addAction ('requestFIRSTRECORD') |
|
|
self.__addAction ('requestPREVRECORD') |
|
|
self.__addAction ('requestNEXTRECORD') |
|
|
self.__addAction ('requestLASTRECORD') |
|
|
self.__addAction (_PROMPTFORRECORD, '_promptForRecord_') |
|
|
self.__addAction ('requestNEWRECORD') |
|
|
self.__addAction ('requestMARKFORDELETE') |
|
|
self.__addAction ('requestNEXTBLOCK') |
|
|
self.__addAction ('requestPREVBLOCK') |
|
|
self.__addAction ('requestENTERQUERY') |
|
|
self.__addAction ('requestEXECQUERY') |
|
|
self.__addAction ('requestABOUT') |
|
177 |
|
|
178 |
self.mainWindow.panel = wxPanel(self.mainWindow,-1, wxDefaultPosition,self.mainWindow.GetClientSize()) |
self.currentWidget = [self._scrollWindow] |
179 |
|
|
180 |
global _disabledColour |
EVT_CLOSE(self.mainWindow,self.closeTrap) |
|
_disabledColour = self.mainWindow.GetBackgroundColour() |
|
181 |
|
|
182 |
self.currentWidget = [self.mainWindow.panel] |
def _activateForm(self, form): |
183 |
#self._wxapp.SetTopWindow(self.mainWindow) |
# |
184 |
|
# Build Menu |
185 |
|
# |
186 |
|
self.menu_sb_space = 0 |
187 |
|
if not form._features['GUI:MENUBAR:SUPPRESS']: |
188 |
|
self.menu_sb_space += 2 |
189 |
|
|
190 |
|
# This will be a dict of the form { 'requestROLLBACK': 1001 } |
191 |
|
# where 1001 is the wxId associated with requestROLLBACK. |
192 |
|
self.__eventMenuMapping = {} |
193 |
|
|
194 |
|
fileMenu = wxMenu() |
195 |
|
self.__addMenuItem(fileMenu, _("&Save\tF6"),_('Save all changes to database.'),'requestCOMMIT', form=form) |
196 |
|
self.__addMenuItem(fileMenu, _("&Clear Form\tF11"),_('Clear Form'),'requestROLLBACK', form=form) |
197 |
|
fileMenu.AppendSeparator() |
198 |
|
|
199 |
|
self.__addMenuItem(fileMenu, _("&Print"),_('Perform print routine for this form.'),'requestPRINTOUT', form=form) |
200 |
|
fileMenu.AppendSeparator() |
201 |
|
|
202 |
|
id = self.__addMenuItem(fileMenu, _("E&xit"),_('Leave the application.'), form=form) |
203 |
|
EVT_MENU(self._wxapp, id, self.menuExitEvent) |
204 |
|
self.__eventMenuMapping['_exit_'] = id |
205 |
|
|
206 |
|
editMenu = wxMenu() |
207 |
|
self.__addMenuItem(editMenu, _("C&ut"),_("Cut the selected text"),'requestCUT', form=form) |
208 |
|
self.__addMenuItem(editMenu, _("&Copy"),_("Copy the selected text"), 'requestCOPY', form=form) |
209 |
|
self.__addMenuItem(editMenu, _("&Paste"),_("Paste text"),'requestPASTE', form=form) |
210 |
|
|
211 |
|
dataMenu = wxMenu() |
212 |
|
self.__addMenuItem(dataMenu, _("&First Record\tCtrl+Up"),_('Navigate to first record in memory.'),'requestFIRSTRECORD', form=form) |
213 |
|
self.__addMenuItem(dataMenu, _("&Previous Record\tUp"),_('Navigate to previous record in memory.'),'requestPREVRECORD', form=form) |
214 |
|
self.__addMenuItem(dataMenu, _("&Next Record\tDown"),_('Navigate to next record in memory.'),'requestNEXTRECORD', form=form) |
215 |
|
self.__addMenuItem(dataMenu, _("&Last Record\tCtrl+Down"),_('Navigate to last record in memory.'),'requestLASTRECORD', form=form) |
216 |
|
id = self.__addMenuItem(dataMenu, _("&Jump to Record...\tF2"),_('Prompts for a record number to which the system should jump.'), form=form) |
217 |
|
EVT_MENU(self._wxapp, id, _PROMPTFORRECORD) |
218 |
|
self.__eventMenuMapping['_promptForRecord_'] = id |
219 |
|
|
220 |
|
self.__addMenuItem(dataMenu, _("N&ew Record\tF12"),_('Create a new record for data input.'),'requestNEWRECORD', form=form) |
221 |
|
self.__addMenuItem(dataMenu, _("Mark Record for &Delete\tF5"),_('Mark record for removal at next commit.'),'requestMARKFORDELETE', form=form) |
222 |
|
|
223 |
|
dataMenu.AppendSeparator() |
224 |
|
self.__addMenuItem(dataMenu, _("Next &Block\tPgDn"),_('Navigate to next data block.'),'requestNEXTBLOCK', form=form) |
225 |
|
self.__addMenuItem(dataMenu, _("P&revious Block\tPgUp"),_('Navigate to previous data block.'),'requestPREVBLOCK', form=form) |
226 |
|
|
227 |
|
dataMenu.AppendSeparator() |
228 |
|
self.__addMenuItem(dataMenu, _("&Enter Query\tF8"),_('Switch to input query mask mode.'),'requestENTERQUERY', form=form) |
229 |
|
self.__addMenuItem(dataMenu, _("Execute &Query\tF9"), _('Execute query using current mask.'),'requestEXECQUERY', form=form) |
230 |
|
|
231 |
|
helpMenu = wxMenu() |
232 |
|
self.__addMenuItem(helpMenu, _("&About..."), _('Display info about GNUe Forms.'),'requestABOUT', form=form) |
233 |
|
|
234 |
|
menuBar = wxMenuBar() |
235 |
|
menuBar.Append( fileMenu, _("&File") ) |
236 |
|
menuBar.Append( editMenu, _("&Edit") ) |
237 |
|
menuBar.Append( dataMenu, _("&Data") ) |
238 |
|
menuBar.Append( helpMenu, _("&Help") ) |
239 |
|
|
240 |
EVT_CLOSE(self.mainWindow,self.closeTrap) |
self._menuBar = menuBar |
241 |
|
self.mainWindow.SetMenuBar( self._menuBar ); |
242 |
|
|
243 |
return true |
# |
244 |
|
# Build Toolbar |
245 |
|
# |
246 |
|
if not form._features['GUI:TOOLBAR:SUPPRESS']: |
247 |
|
|
248 |
|
self.menu_sb_space += 2 |
249 |
|
# |
250 |
|
# There has got to be better way to call events to ride off the EVT_MENU |
251 |
|
# Ok if i give buttons same id as menu's they share events |
252 |
|
# I dont know if this is horribly wrong or design |
253 |
|
# |
254 |
|
if sys.platform == 'win32': |
255 |
|
mainToolBar = wxToolBar(self.mainWindow, -1) |
256 |
|
else: |
257 |
|
mainToolBar = wxToolBar(self.mainWindow,-1, style=wxTB_HORIZONTAL|wxTB_DOCKABLE) |
258 |
|
|
259 |
|
mainToolBar.SetToolBitmapSize(wxSize(24,24)) |
260 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestCOMMIT'], wxImage(images_dir+gConfigForms('tb_commit'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Save Changes"), _('Save all changes to database.')) |
261 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestNEWRECORD'], wxImage(images_dir+gConfigForms('tb_insert'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Insert Record"), _('Create a new record for data input.')) |
262 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestMARKFORDELETE'], wxImage(images_dir+gConfigForms('tb_delete'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Delete Record"), _('Mark record for removal at next commit.')) |
263 |
|
mainToolBar.AddSeparator() |
264 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestFIRSTRECORD'], wxImage(images_dir+gConfigForms('tb_first'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("First Record"),_('Navigate to first record in memory.')) |
265 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestPREVRECORD'], wxImage(images_dir+gConfigForms('tb_previous'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Previous Record"),_('Navigate to previous record in memory.')) |
266 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestNEXTRECORD'], wxImage(images_dir+gConfigForms('tb_next'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Next Record"),_('Navigate to next record in memory.')) |
267 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestLASTRECORD'], wxImage(images_dir+gConfigForms('tb_last'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Last Record"),_('Navigate to last record in memory.')) |
268 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['_promptForRecord_'], wxImage(images_dir+gConfigForms('tb_jump'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Jump to Record"),_('Navigate to user specified record in memory.')) |
269 |
|
mainToolBar.AddSeparator() |
270 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestENTERQUERY'], wxImage(images_dir+gConfigForms('tb_query_prep'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Prepare Query"), _('Switch to input query mask mode.')) |
271 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestEXECQUERY'], wxImage(images_dir+gConfigForms('tb_query'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Execute Query"), _('Execute query using current mask.')) |
272 |
|
mainToolBar.AddSeparator() |
273 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestROLLBACK'], wxImage(images_dir+gConfigForms('tb_rollback'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Clear Form"), _('Clear Form')) |
274 |
|
mainToolBar.AddSimpleTool(self.__eventMenuMapping['_exit_'], wxImage(images_dir+gConfigForms('tb_exit'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Exit Form"), _('Exit Form')) |
275 |
|
|
276 |
|
self._mainToolBar = mainToolBar |
277 |
|
self.mainWindow.SetToolBar( mainToolBar ); |
278 |
|
self._mainToolBar.Realize() |
279 |
|
|
280 |
def activateForm(self, form): |
|
281 |
width = int(self._form.width) |
# |
282 |
height = int(self._form.height) |
# Size based upon the form definition |
283 |
|
# |
284 |
|
width = int(self._form._layout.Char__width) |
285 |
|
height = int(self._form._layout.Char__height) |
286 |
|
|
287 |
formSize = wxSize(width*self.widgetWidth, |
formSize = wxSize(width*self.widgetWidth, |
288 |
(height+self.menu_sb_space)*self.widgetHeight) |
(height+self.menu_sb_space)*self.widgetHeight) |
289 |
|
|
290 |
self.mainWindow.SetSize(formSize) |
self.mainWindow.SetSize(formSize) |
291 |
self.mainWindow.SetTitle(str(self._form.title)) |
self.mainWindow.SetTitle(str(self._form.title)) |
|
self.mainWindow.panel = self._pageList[0] |
|
|
self.mainWindow.panel.SetSize(formSize) |
|
|
self._pageList[0].Show(TRUE) |
|
|
|
|
|
# Only one page at a time can be visible |
|
|
self.visiblePage = self._pageList[0] |
|
292 |
|
|
293 |
if self._notebook: # Adjust sizes |
if self._notebook: # Adjust sizes |
294 |
self._notebook.SetClientSize(formSize) |
self._notebook.SetClientSize(formSize) |
298 |
child.Fit() |
child.Fit() |
299 |
child = child.GetParent() |
child = child.GetParent() |
300 |
|
|
301 |
self._wxapp.SetTopWindow(self.mainWindow) |
# This is the initial panel window setup during init |
302 |
|
# not a wxPanel set per page right after this |
303 |
|
tempx,tempy = self.mainWindow.GetClientSizeTuple() |
304 |
|
self._scrollWindow.SetScrollbars(1, 1, tempx, tempy) |
305 |
|
|
306 |
|
self.mainWindow.panel = self._pageList[0] |
307 |
|
self.mainWindow.panel.SetSize(self.mainWindow.GetClientSize()) |
308 |
|
self.mainWindow.panel.Raise() |
309 |
|
|
310 |
|
# Only one page at a time can be visible |
311 |
|
self.visiblePage = self._pageList[0] |
312 |
|
self.visiblePage.Show(TRUE) |
313 |
|
#self.visiblePage.Raise() |
314 |
|
#self._wxapp.SetTopWindow(self.mainWindow) |
315 |
|
|
316 |
|
# TODO: Scrollbar width adjustment? |
317 |
|
tempx,tempy = self.mainWindow.GetSizeTuple() |
318 |
|
mainWindowSize = wxSize(20+tempx, 20+tempy) |
319 |
|
self.mainWindow.SetSize(mainWindowSize) |
320 |
|
|
321 |
|
# Go ahead and display |
322 |
self.mainWindow.CenterOnScreen() |
self.mainWindow.CenterOnScreen() |
323 |
self.mainWindow.Show(true) |
self.mainWindow.Show(true) |
324 |
# Keep splash on top |
|
325 |
if hasattr(self,'splash'): |
# Ensure splashscreen is on top |
326 |
self.splash.Raise() |
#if hasattr(self,'splash') and self.splash: |
327 |
|
# self.splash.Raise() |
328 |
|
|
329 |
############################################################################# |
############################################################################# |
330 |
# |
# |
346 |
# |
# |
347 |
# Internal helper function to add a menu item and an event |
# Internal helper function to add a menu item and an event |
348 |
# |
# |
349 |
def __addAction(self, event=None, name=None): |
def __addMenuItem(self, menu, text, help, event=None, form=None): |
350 |
id = wxNewId() |
id = wxNewId() |
351 |
|
menu.Append(id, text, help) |
352 |
if event: |
if event: |
353 |
if type(event)==types.StringType: |
EVT_MENU(self._wxapp, id, |
354 |
# a 'requestTHING' event |
lambda event, l=self, e=event, f=form: l.dispatchEvent(events.Event(e,_form=f))) |
355 |
EVT_MENU(self._wxapp, id, lambda event, l=self, e=event: l.dispatchEvent(events.Event(e))) |
self.__eventMenuMapping[event] = id |
356 |
self.__eventActionMapping[event] = id |
|
|
else: |
|
|
# a simple function |
|
|
EVT_MENU(self._wxapp, id, event) |
|
|
self.__eventActionMapping[name] = id |
|
357 |
return id |
return id |
358 |
|
|
|
def _addMenuItem (self, menu, text, help, eventName): |
|
|
menu.Append(self.__eventActionMapping[eventName], text, help) |
|
|
|
|
|
def _addToolButton (self, toolBar, eventName, image, toolTip, sbHint): |
|
|
toolBar.AddSimpleTool(self.__eventActionMapping[eventName], |
|
|
wxImage(images_dir+gConfig(image),wxBITMAP_TYPE_PNG).ConvertToBitmap(), toolTip, sbHint) |
|
359 |
|
|
360 |
# |
# |
361 |
# _setStatusBar |
# _setStatusBar |
407 |
# Incoming Event Processors |
# Incoming Event Processors |
408 |
# |
# |
409 |
# Processes the incoming events from other objects |
# Processes the incoming events from other objects |
410 |
# |
# From here down should be nothing but eventListeners listed |
411 |
|
|
412 |
# |
# |
413 |
# mainLoop |
# mainLoop |
414 |
# |
# |
428 |
self.visiblePage.Show(FALSE) |
self.visiblePage.Show(FALSE) |
429 |
self.visiblePage = self._formToUI[event.data][0] |
self.visiblePage = self._formToUI[event.data][0] |
430 |
# TODO: move the calculatoin out of here |
# TODO: move the calculatoin out of here |
431 |
self.visiblePage.SetSize(wxSize(self._form.width*self.widgetWidth, |
self.visiblePage.SetSize(wxSize(self._form._layout.Char__width*self.widgetWidth, |
432 |
(self._form.height+self.menu_sb_space)*self.widgetHeight)) |
(self._form._layout.Char__height+self.menu_sb_space)*self.widgetHeight)) |
433 |
else: |
else: |
434 |
self.visiblePage = self._formToUI[event.data][0] |
self.visiblePage = self._formToUI[event.data][0] |
435 |
for count in range(self._notebook.GetPageCount()): |
for count in range(self._notebook.GetPageCount()): |
523 |
# |
# |
524 |
# Presents a dialog to user asking for the record number to jump to |
# Presents a dialog to user asking for the record number to jump to |
525 |
# |
# |
526 |
def promptForRecordNumber(self, event= None): |
def promptForRecordNumber(self, event=None): |
527 |
dlg = wxTextEntryDialog(self.mainWindow, _('Enter record number to jump to'), |
dlg = wxTextEntryDialog(self.mainWindow, _('Enter record number to jump to'), |
528 |
_('Which record?')) |
_('Which record?')) |
529 |
|
|
530 |
|
form = _IdToGFObj[self.mainWindow.panel.GetId()].findParentOfType('GFForm') |
531 |
|
|
532 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
533 |
action = self.dispatchEvent(events.Event('requestRECORDNUMBER', dlg.GetValue())) |
action = self.dispatchEvent('requestRECORDNUMBER', dlg.GetValue(), _form=form) |
534 |
else: |
else: |
535 |
action = None |
action = None |
536 |
|
|
545 |
# back an event closing the application |
# back an event closing the application |
546 |
#` |
#` |
547 |
def closeTrap(self,event): |
def closeTrap(self,event): |
548 |
object = _eventObjTowxWindow(event) |
form = _IdToGFObj[self.mainWindow.panel.GetId()].findParentOfType('GFForm') |
549 |
|
|
550 |
if event.CanVeto(): |
if event.CanVeto(): |
551 |
self.dispatchEvent(events.Event('requestEXIT')) |
self.dispatchEvent('requestEXIT',_form=form) |
552 |
else: |
else: |
553 |
|
object = _eventObjTowxWindow(event) |
554 |
object.Destroy() |
object.Destroy() |
555 |
|
# wxExit() TODO: Try and work this into navigator or here if it still hangs |
|
# Called by SplashScreen when timer expires |
|
|
def onCloseSplash(self): |
|
|
# If the splashscreen has timed out before the form is |
|
|
# ready then go ahead and display what we've got. This |
|
|
# is a desperate attempt to eliminate the vile |
|
|
# |
|
|
# Gdk-ERROR **: BadWindow (invalid Window parameter) |
|
|
# serial 1228 error_code 3 request_code 15 minor_code 0 |
|
|
# |
|
|
# on heavily loaded machines. The key line seems to be |
|
|
# wxYield() but I'm leaving the others there because I |
|
|
# can :P The fix works for me all the way down to a |
|
|
# splash duration=1 millisecond |
|
|
# |
|
|
self._wxapp.SetTopWindow(self.mainWindow) |
|
|
self.mainWindow.Show(true) |
|
|
wxYield() # Flush the pending queue to insure something is |
|
|
# there before the splashscreen dies |
|
|
|
|
|
# For some reason, a simple Close() doesn't cooperate with |
|
|
# the modal login box and all hell breaks loose |
|
|
self.splash.Show(0) |
|
|
self.splash.Destroy() |
|
|
|
|
556 |
|
|
557 |
############################################################################# |
############################################################################# |
558 |
############################################################################# |
############################################################################# |
570 |
# UIHelper |
# UIHelper |
571 |
# |
# |
572 |
# Provides a UI widget set of std functions to reduce the number of functions |
# Provides a UI widget set of std functions to reduce the number of functions |
573 |
# require in each UIclass listed below |
# require in each UIclass listed below. |
574 |
class UIHelper: |
# |
575 |
|
class UIHelper(UIWidget): |
576 |
|
# |
577 |
|
# Functions limited to the wx driver |
578 |
|
# |
579 |
|
def _addToCrossRef(self, widget,gfobject, uiobject): |
580 |
|
id = widget.GetId() |
581 |
|
_IdToWxObj[id]=widget |
582 |
|
_IdToGFObj[id]=gfobject |
583 |
|
_IdToUIObj[id]=uiobject |
584 |
|
widget.__origBackgroundColor = widget.GetBackgroundColour() |
585 |
|
|
586 |
|
def _deleteFromCrossRef(self, widget, object): |
587 |
|
id = widget.GetId() |
588 |
|
try: |
589 |
|
del _IdToWxObj[id] |
590 |
|
del _IdToGFObj[id] |
591 |
|
del _IdToUIObj[id] |
592 |
|
except: |
593 |
|
pass |
594 |
|
|
595 |
|
# |
596 |
|
# Override the base UIWidget functions |
597 |
|
# |
598 |
def showModal(self): |
def showModal(self): |
599 |
self.ShowModal() |
self.ShowModal() |
600 |
|
|
|
def show(self, flag=TRUE): |
|
|
self.Show(flag) |
|
|
|
|
601 |
def destroy(self): |
def destroy(self): |
602 |
self.Destroy() |
self.Destroy() |
603 |
|
|
610 |
widget = self.widgets[index] |
widget = self.widgets[index] |
611 |
widget.SetEvtHandlerEnabled(FALSE) |
widget.SetEvtHandlerEnabled(FALSE) |
612 |
|
|
|
|
|
613 |
# Check if foreign key changed |
# Check if foreign key changed |
614 |
object = _IdToGFObj[widget.GetId()] |
object = _IdToGFObj[widget.GetId()] |
615 |
try: |
try: |
616 |
if object.style == "dropdown" and \ |
if object.style == "dropdown" and \ |
617 |
not object._allowedValues == widget._origAllowedValues: |
not object._field._allowedValues == widget._origAllowedValues: |
618 |
widget._origAllowedValues = object._allowedValues |
try: |
619 |
|
# Not in wx 2.2.x |
620 |
|
widget.Freeze() |
621 |
|
except AttributeError: |
622 |
|
pass |
623 |
|
widget._origAllowedValues = object._field._allowedValues |
624 |
widget.Clear() |
widget.Clear() |
625 |
for value in object._allowedValuesDescr: |
for value in object._field._allowedValuesDescr: |
626 |
widget.Append(value) |
widget.Append(value) |
627 |
|
try: |
628 |
|
# Not in wx 2.2.x |
629 |
|
widget.Thaw() |
630 |
|
except AttributeError: |
631 |
|
pass |
632 |
except AttributeError: |
except AttributeError: |
633 |
pass |
pass |
634 |
|
|
653 |
except (AttributeError, TypeError): |
except (AttributeError, TypeError): |
654 |
pass # For label-style & dropdown entries |
pass # For label-style & dropdown entries |
655 |
|
|
|
|
|
|
def _addToCrossRef(self, widget,gfobject, uiobject): |
|
|
id = widget.GetId() |
|
|
_IdToWxObj[id]=widget |
|
|
_IdToGFObj[id]=gfobject |
|
|
_IdToUIObj[id]=uiobject |
|
|
widget.__origBackgroundColor = widget.GetBackgroundColour() |
|
|
|
|
|
|
|
|
def _deleteFromCrossRef(self, widget, object): |
|
|
id = widget.GetId() |
|
|
try: |
|
|
del _IdToWxObj[id] |
|
|
del _IdToGFObj[id] |
|
|
del _IdToUIObj[id] |
|
|
except: |
|
|
pass |
|
|
|
|
|
|
|
656 |
def createWidget(self, event, spacer): |
def createWidget(self, event, spacer): |
|
|
|
657 |
newWidget = self._createWidget(event, spacer) |
newWidget = self._createWidget(event, spacer) |
658 |
initFont(newWidget) |
initFont(newWidget) |
659 |
self._addToCrossRef(newWidget,event.object,self) |
self._addToCrossRef(newWidget,event.object,self) |
668 |
self.widgets.pop(0) |
self.widgets.pop(0) |
669 |
self._deleteFromCrossRef(widget, object) |
self._deleteFromCrossRef(widget, object) |
670 |
|
|
|
|
|
|
class UIMainMenuBar (UIHelper, UIWidget): |
|
|
def _createWidget (self, event, spacer): |
|
|
iface= event.interface |
|
|
window= iface.mainWindow |
|
|
|
|
|
fileMenu = wxMenu() |
|
|
iface._addMenuItem(fileMenu, _("Save (F6)"),_('Save all changes to database.'),'requestCOMMIT') |
|
|
iface._addMenuItem(fileMenu, _("Clear Form (F11)"),_('Clear Form'),'requestROLLBACK') |
|
|
fileMenu.AppendSeparator() |
|
|
|
|
|
iface._addMenuItem(fileMenu, _("&Print"),_('Perform print routine for this form.'),'requestPRINTOUT') |
|
|
fileMenu.AppendSeparator() |
|
|
|
|
|
iface._addMenuItem(fileMenu, _("E&xit"),_('Leave the application.'), '_exit_') |
|
|
|
|
|
editMenu = wxMenu() |
|
|
iface._addMenuItem(editMenu, _("Cut"),_("Cut the selected text"),'requestCUT') |
|
|
iface._addMenuItem(editMenu, _("Copy"),_("Copy the selected text"), 'requestCOPY') |
|
|
iface._addMenuItem(editMenu, _("Paste"),_("Paste text"),'requestPASTE') |
|
|
|
|
|
dataMenu = wxMenu() |
|
|
iface._addMenuItem(dataMenu, _("First Record (Shft+Up)"),_('Navigate to first record in memory.'),'requestFIRSTRECORD') |
|
|
iface._addMenuItem(dataMenu, _("Previous Record (Up)"),_('Navigate to previous record in memory.'),'requestPREVRECORD') |
|
|
iface._addMenuItem(dataMenu, _("Next Record (Down)"),_('Navigate to next record in memory.'),'requestNEXTRECORD') |
|
|
iface._addMenuItem(dataMenu, _("Last Record (Shft+Down)"),_('Navigate to last record in memory.'),'requestLASTRECORD') |
|
|
iface._addMenuItem(dataMenu, _("Jump to Record... (F2)"),_('Prompts for a record number to which the system should jump.'), '_promptForRecord_') |
|
|
|
|
|
iface._addMenuItem(dataMenu, _("New Record (F12)"),_('Create a new record for data input.'),'requestNEWRECORD') |
|
|
iface._addMenuItem(dataMenu, _("Mark Record for Delete (F5)"),_('Mark record for removal at next commit.'),'requestMARKFORDELETE') |
|
|
|
|
|
dataMenu.AppendSeparator() |
|
|
iface._addMenuItem(dataMenu, _("Next Block (PgDn)"),_('Navigate to next data block.'),'requestNEXTBLOCK') |
|
|
iface._addMenuItem(dataMenu, _("Previous Block (PgUp)"),_('Navigate to previous data block.'),'requestPREVBLOCK') |
|
|
|
|
|
dataMenu.AppendSeparator() |
|
|
iface._addMenuItem(dataMenu, _("Enter Query (F8)"),_('Switch to input query mask mode.'),'requestENTERQUERY') |
|
|
iface._addMenuItem(dataMenu, _("Execute Query (F9)"), _('Execute query using current mask.'),'requestEXECQUERY') |
|
|
|
|
|
helpMenu = wxMenu() |
|
|
iface._addMenuItem(helpMenu, _("&About..."), _('Display info about GNUe Forms.'),'requestABOUT') |
|
|
|
|
|
menuBar = wxMenuBar() |
|
|
menuBar.Append( fileMenu, _("&File") ) |
|
|
menuBar.Append( editMenu, _("&Edit") ) |
|
|
menuBar.Append( dataMenu, _("&Data") ) |
|
|
menuBar.Append( helpMenu, _("&Help") ) |
|
|
|
|
|
window.SetMenuBar( menuBar ) |
|
|
|
|
|
return menuBar |
|
|
|
|
|
class UIMainToolBar (UIHelper, UIWidget): |
|
|
def _createWidget (self, event, spacer): |
|
|
iface= event.interface |
|
|
window= iface.mainWindow |
|
|
|
|
|
# |
|
|
# There has got to be better way to call events to ride off the EVT_MENU |
|
|
# Ok if i give buttons same id as menu's they share events |
|
|
# I dont know if this is horribly wrong or design |
|
|
# |
|
|
if sys.platform == 'win32': |
|
|
mainToolBar = window.CreateToolBar() |
|
|
else: |
|
|
mainToolBar = window.CreateToolBar(wxTB_HORIZONTAL|wxTB_DOCKABLE) |
|
|
|
|
|
mainToolBar.SetToolBitmapSize(wxSize(24,24)) |
|
|
iface._addToolButton (mainToolBar, 'requestCOMMIT', 'tb_commit', _("Save Changes"), _('Save all changes to database.')) |
|
|
iface._addToolButton (mainToolBar, 'requestNEWRECORD', 'tb_insert', _("Insert Record"), _('Create a new record for data input.')) |
|
|
iface._addToolButton (mainToolBar, 'requestMARKFORDELETE', 'tb_delete', _("Delete Record"), _('Mark record for removal at next commit.')) |
|
|
mainToolBar.AddSeparator() |
|
|
iface._addToolButton (mainToolBar, 'requestFIRSTRECORD', 'tb_first', _("First Record"),_('Navigate to first record in memory.')) |
|
|
iface._addToolButton (mainToolBar, 'requestPREVRECORD', 'tb_previous', _("Previous Record"),_('Navigate to previous record in memory.')) |
|
|
iface._addToolButton (mainToolBar, 'requestNEXTRECORD', 'tb_next', _("Next Record"),_('Navigate to next record in memory.')) |
|
|
iface._addToolButton (mainToolBar, 'requestLASTRECORD', 'tb_last', _("Last Record"),_('Navigate to last record in memory.')) |
|
|
iface._addToolButton (mainToolBar, '_promptForRecord_', 'tb_jump', _("Jump to Record"),_('Navigate to user specified record in memory.')) |
|
|
mainToolBar.AddSeparator() |
|
|
iface._addToolButton (mainToolBar, 'requestENTERQUERY', 'tb_query_prep', _("Prepare Query"), _('Switch to input query mask mode.')) |
|
|
iface._addToolButton (mainToolBar, 'requestEXECQUERY', 'tb_query', _("Execute Query"), _('Execute query using current mask.')) |
|
|
mainToolBar.AddSeparator() |
|
|
iface._addToolButton (mainToolBar, 'requestROLLBACK', 'tb_rollback', _("Clear Form"), _('Clear Form')) |
|
|
iface._addToolButton (mainToolBar, '_exit_', 'tb_exit', _("Exit Form"), _('Exit Form')) |
|
|
mainToolBar.Realize() |
|
|
|
|
|
return mainToolBar |
|
|
|
|
671 |
# |
# |
672 |
# UILabel |
# UILabel |
673 |
# |
# |
674 |
# Widget set specific function that creates a single instance of a label |
# Widget set specific function that creates a single instance of a label |
675 |
# |
# |
676 |
class UILabel(UIHelper, UIWidget): |
class UILabel(UIHelper): |
677 |
alignmentStyle = { 'left' : wxALIGN_LEFT|wxST_NO_AUTORESIZE, |
alignmentStyle = { 'left' : wxALIGN_LEFT|wxST_NO_AUTORESIZE, |
678 |
'center': wxALIGN_CENTRE|wxST_NO_AUTORESIZE, |
'center': wxALIGN_CENTRE|wxST_NO_AUTORESIZE, |
679 |
'right' : wxALIGN_RIGHT|wxST_NO_AUTORESIZE, |
'right' : wxALIGN_RIGHT|wxST_NO_AUTORESIZE, |
680 |
} |
} |
681 |
|
|
682 |
|
|
683 |
def _createWidget(self, event, spacer): |
def _createWidget(self, event, spacer): |
684 |
object = event.object |
object = event.object |
685 |
style = self.alignmentStyle[object.alignment] |
style = self.alignmentStyle[object.alignment] |
686 |
newWidget = wxStaticText(event.container, -1, str(object.text), |
newWidget = wxStaticText(event.container, -1, str(object.text), |
687 |
wxPoint(object.x*event.widgetWidth, |
wxPoint(object.Char__x*event.widgetWidth, |
688 |
(object.y+spacer+(spacer*object._gap))*event.widgetHeight), |
(object.Char__y+spacer+(spacer*object._gap))*event.widgetHeight), |
689 |
wxSize(self.itemWidth,self.itemHeight), style) |
wxSize(self.itemWidth,self.itemHeight), style) |
690 |
return newWidget |
return newWidget |
691 |
|
|
694 |
# |
# |
695 |
# Widget set specific function that creates a single instance of a border box |
# Widget set specific function that creates a single instance of a border box |
696 |
# |
# |
697 |
class UIBox(UIHelper, UIWidget): |
class UIBox(UIHelper): |
698 |
def _createWidget(self, event, spacer): |
def _createWidget(self, event, spacer): |
699 |
|
|
700 |
object = event.object |
object = event.object |
701 |
|
newWidget = wxStaticBox(event.container,-1,str(object.label), |
702 |
# this panel makes the GFBox be a container |
wxPoint(object.Char__x*event.widgetWidth+(event.widgetWidth/2), |
703 |
newPanel = wxPanel(event.container,-1, |
(object.Char__y+spacer+(spacer*object._gap))*event.widgetHeight+(event.widgetHeight/2)), |
704 |
wxPoint(object.x*event.widgetWidth+(event.widgetWidth/2), |
wxSize((object.Char__width-1)*event.widgetWidth, |
705 |
(object.y+spacer+(spacer*object._gap))*event.widgetHeight+(event.widgetHeight/2)), |
(object.Char__height-1)*event.widgetHeight)) |
706 |
wxSize((object.width-1)*event.widgetWidth, |
return newWidget |
|
(object.height-1)*event.widgetHeight)) |
|
|
newWidget = wxStaticBox(newPanel,-1,str(object.label), |
|
|
wxPoint(0, 0), |
|
|
wxSize((object.width-1)*event.widgetWidth, |
|
|
(object.height-1)*event.widgetHeight)) |
|
|
return newPanel |
|
707 |
|
|
708 |
# |
# |
709 |
# UIScrollBar |
# UIScrollBar |
711 |
# Widget set specific function that creates a single instance of a scroll bar used |
# Widget set specific function that creates a single instance of a scroll bar used |
712 |
# to navigate multiple records |
# to navigate multiple records |
713 |
# |
# |
714 |
class UIScrollBar(UIHelper, UIWidget): |
class UIScrollBar(UIHelper): |
715 |
# this one maps wx's scroll to gnue's scroll. |
# this one maps wx's scroll to gnue's scroll. |
716 |
wxToScroll= { |
wxToScroll= { |
717 |
10302: 0, # line up |
10302: 0, # line up |
720 |
10305: 3, # page down |
10305: 3, # page down |
721 |
10303: 4 # line down |
10303: 4 # line down |
722 |
} |
} |
|
|
|
723 |
def _createWidget(self, event, spacer): |
def _createWidget(self, event, spacer): |
724 |
object = event.object |
object = event.object |
725 |
self._page= object.page |
self._page= object.page |
726 |
self._widget= wxScrollBar(event.container,-1, |
self._widget=wxScrollBar(event.container,-1, |
727 |
wxPoint(object.x*event.widgetWidth,(object.y+spacer)*event.widgetHeight), |
wxPoint(object.Char__x*event.widgetWidth,(object.Char__y+spacer)*event.widgetHeight), |
728 |
wxSize(object.width*event.widgetWidth,object.height*event.widgetHeight), |
wxSize(object.Char__width*event.widgetWidth,object.Char__height*event.widgetHeight), |
729 |
wxSB_VERTICAL) |
wxSB_VERTICAL) |
730 |
# tie |
# tie |
731 |
if event.initialize: |
if event.initialize: |
738 |
# how? I need a eventAware thing! |
# how? I need a eventAware thing! |
739 |
# registerEventListeners () |
# registerEventListeners () |
740 |
# or find the block and cross register. |
# or find the block and cross register. |
741 |
block= object.findParentOfType ('GFBlock') |
block= object.findParentOfType('GFForm')._logic._blockMap[object.block] |
742 |
block.registerScrollBar (self) |
block.registerScrollBar (self) |
743 |
|
|
744 |
return self._widget |
return self._widget |
745 |
|
|
746 |
def scroll (self, event): |
def scroll (self, event): |
747 |
try: |
try: |
748 |
action = events.Event('requestSCROLL', (self.wxToScroll[event.GetEventType()], self._page)) |
action = events.Event('requestSCROLL', (self.wxToScroll[event.GetEventType()], self._page)) |
749 |
|
action._form = self._form |
750 |
self._eventHandler(action) |
self._eventHandler(action) |
751 |
except KeyError, e: |
except KeyError, e: |
752 |
# ignore; it's not a event we want to handle |
# ignore; it's not a event we want to handle |
753 |
# e.g., click on the sb's handle |
# e.g., click on the sb's handle |
754 |
pass |
pass |
755 |
|
|
756 |
# int position, int thumbSize, int range, int pageSize, const bool refresh = TRUE |
# int position, int thumbSize, int range, int pageSize, const bool refresh = TRUE |
757 |
def update (self, pos, range): |
def update (self, pos, range): |
758 |
# print pos, range |
# print pos, range |
759 |
self._widget.SetScrollbar (pos, 1, range, self._page-1) |
self._widget.SetScrollbar (pos, 1, range, self._page-1) |
760 |
|
|
761 |
|
|
762 |
# |
# |
763 |
# UIButton |
# UIButton |
764 |
# |
# |
765 |
# Widget set specific function that creates a single instance of a button |
# Widget set specific function that creates a single instance of a button |
766 |
# |
# |
767 |
class UIButton(UIHelper, UIWidget): |
class UIButton(UIHelper): |
768 |
def _createWidget(self, event, spacer): |
def _createWidget(self, event, spacer): |
769 |
object = event.object |
object = event.object |
770 |
newWidget = wxButton(event.container,-1,str(object.label), |
newWidget = wxButton(event.container,-1,str(object.label), |
771 |
wxPoint(object.x*event.widgetWidth,(object.y+spacer)*event.widgetHeight), |
wxPoint(object.Char__x*event.widgetWidth,(object.Char__y+spacer)*event.widgetHeight), |
772 |
wxSize(object.width*event.widgetWidth,object.height*event.widgetHeight) |
wxSize(object.Char__width*event.widgetWidth,object.Char__height*event.widgetHeight) |
773 |
) |
) |
774 |
if event.initialize: |
if event.initialize: |
775 |
self._eventHandler = event.eventHandler |
self._eventHandler = event.eventHandler |
785 |
|
|
786 |
id = object.GetId() |
id = object.GetId() |
787 |
gfObject = _IdToGFObj[id] |
gfObject = _IdToGFObj[id] |
788 |
action = events.Event('fireTRIGGER',gfObject.trigger) |
action = events.Event('buttonActivated',gfObject) |
789 |
self._eventHandler(action) |
self._eventHandler(action) |
790 |
|
|
791 |
|
|
796 |
# |
# |
797 |
# Note: The event trap for changing notebook pages is attached to the UIForm |
# Note: The event trap for changing notebook pages is attached to the UIForm |
798 |
# |
# |
799 |
class UIPage(UIHelper, UIWidget): |
class UIPage(UIHelper): |
800 |
def _createWidget(self, event, spacer): |
def _createWidget(self, event, spacer): |
801 |
object = event.object |
object = event.object |
802 |
if event.interface._notebook: |
if event.interface._notebook: |
803 |
newWidget = wxPanel(event.interface._notebook, -1,wxDefaultPosition,event.interface._notebook.GetClientSize()) |
newWidget = wxPanel(event.interface._notebook, -1,wxDefaultPosition,event.interface._notebook.GetClientSize()) |
804 |
event.interface._notebook.AddPage(newWidget,hasattr(object,'caption') and object.caption or object.name) |
event.interface._notebook.AddPage(newWidget,hasattr(object,'caption') and object.caption or object.name) |
805 |
newWidget.Show(1) |
if sys.platform == 'win32': |
806 |
|
newWidget.Show(0) |
807 |
|
else: |
808 |
|
newWidget.Show(1) |
809 |
else: |
else: |
810 |
newWidget = wxPanel(event.container, -1,wxDefaultPosition,event.container.GetSize()) |
newWidget = wxPanel(event.container, -1,wxDefaultPosition,event.container.GetSize()) |
811 |
newWidget.Show(0) |
newWidget.Show(0) |
820 |
# |
# |
821 |
# Widget set specific function that creates a single instance of a data entry widget |
# Widget set specific function that creates a single instance of a data entry widget |
822 |
# |
# |
823 |
class UIEntry(UIHelper, UIWidget): |
class UIEntry(UIHelper): |
824 |
def _createWidget(self, event, spacer): |
def _createWidget(self, event, spacer): |
825 |
object = event.object |
object = event.object |
826 |
|
|
827 |
style = object.style |
style = object.style |
828 |
defaultPoint = wxPoint(object.x*event.widgetWidth, |
defaultPoint = wxPoint(object.Char__x*event.widgetWidth, |
829 |
(object.y+spacer+(object._gap*spacer))*event.widgetHeight) |
(object.Char__y+spacer+(object._gap*spacer))*event.widgetHeight) |
830 |
defaultSize = wxSize(self.itemWidth,self.itemHeight+1) |
defaultSize = wxSize(self.itemWidth,self.itemHeight+1) |
831 |
|
|
832 |
if style == 'dropdown': |
if style == 'dropdown': |
833 |
if event.initialize: |
if event.initialize: |
834 |
choices = object.allowedValues()[1] |
choices = object._field.allowedValues()[1] |
835 |
else: |
else: |
836 |
choices = [""] |
choices = [""] |
837 |
|
|
838 |
newWidget = wxComboBox(event.container, -1, "",defaultPoint, |
newWidget = wxComboBox(event.container, -1, "",defaultPoint, |
839 |
wxSize(self.itemWidth,self.itemHeight), |
wxSize(self.itemWidth,self.itemHeight), |
840 |
choices, wxCB_DROPDOWN,) # |wxWANTS_CHARS,) |
choices, wxCB_DROPDOWN,) # |wxWANTS_CHARS,) |
841 |
newWidget._origAllowedValues = object._allowedValues |
if event.initialize: |
842 |
|
newWidget._origAllowedValues = object._field._allowedValues |
843 |
newWidget.SetValue("") |
newWidget.SetValue("") |
844 |
EVT_COMBOBOX(newWidget, newWidget.GetId(), self.comboHandler) |
EVT_COMBOBOX(newWidget, newWidget.GetId(), self.comboHandler) |
845 |
|
|
846 |
elif style == 'textlookup': |
elif style == 'textlookup': |
847 |
newWidget = wxStaticText(event.container, -1, "",defaultPoint,defaultSize, |
newWidget = wxStaticText(event.container, -1, "",defaultPoint,defaultSize, |
861 |
newWidget = wxCheckBox(event.container, -1, "",defaultPoint, |
newWidget = wxCheckBox(event.container, -1, "",defaultPoint, |
862 |
wxSize(2*event.textWidth,event.textHeight), |
wxSize(2*event.textWidth,event.textHeight), |
863 |
wxNO_BORDER) |
wxNO_BORDER) |
864 |
newWidget.SetValue(0) |
if event.initialize: |
865 |
|
newWidget.SetValue(0) |
866 |
|
EVT_CHECKBOX(newWidget, newWidget.GetId(), self.checkboxHandler) |
867 |
|
|
868 |
else: # Normal text box |
else: # Normal text box |
869 |
if event.initialize: |
if event.initialize: |
870 |
styles = wxTE_PROCESS_TAB |
styles = wxTE_PROCESS_TAB |
871 |
if object.height > 1: |
if hasattr(object,'Char__height') and object.Char__height > 1: |
872 |
styles = styles|wxTE_MULTILINE |
styles = styles|wxTE_MULTILINE |
873 |
value = "" ## object.getValue() |
value = "" ## object.getValue() |
874 |
else: |
else: |
891 |
gfObject = _IdToGFObj[id] |
gfObject = _IdToGFObj[id] |
892 |
eventdata = [gfObject, event.GetString()] |
eventdata = [gfObject, event.GetString()] |
893 |
action = events.Event('requestREPLACEVALUE',object=gfObject, |
action = events.Event('requestREPLACEVALUE',object=gfObject, |
894 |
index=selection, text=event.GetString()) |
index=selection, text=event.GetString(), |
895 |
|
_form=gfObject._form) |
896 |
self._eventHandler(action) |
self._eventHandler(action) |
897 |
|
|
898 |
def checkboxHandler(self,event): |
def checkboxHandler(self,event): |
899 |
if event.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED: |
if event.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED: |
900 |
# hack for swig shortcomming |
object = _eventObjTowxWindow(event) |
901 |
eo = event.GetEventObject() |
id = object.GetId() |
902 |
object = wxPyTypeCast(eo, 'wxCheckBox') |
|
903 |
# TODO: this doesn't work yet :) |
gfObject = _IdToGFObj[id] |
904 |
#for key in self._formToUI.keys(): |
eventdata = [gfObject, event.GetString()] |
905 |
# for count in range(len(self._formToUI[key])): |
action = events.Event('requestTOGGLECHKBOX', _form=gfObject._form) |
906 |
# if self._formToUI[key][count].GetId() == object.GetId(): |
self._eventHandler(action) |
|
# self.dispatchEvent(events.Event('requestFOCUS',key)) |
|
|
# eventdata = [key, object.GetValue()] |
|
|
# self.dispatchEvent(events.Event('requestJUMPRECORD',count - key._visibleIndex)) |
|
|
# self.dispatchEvent(events.Event('requestTOGGLECHKBOX',eventdata)) |
|
|
# break |
|
|
|
|
|
#if action: |
|
|
# self.dispatchEvent(action) |
|
|
|
|
|
|
|
907 |
|
|
908 |
# |
# |
909 |
# UIForm |
# UIForm |
910 |
# |
# |
911 |
# Widget set specific function that creates a single instance of a Form widget |
# Widget set specific function that creates a single instance of a Form widget |
912 |
# |
# |
913 |
class UIForm(UIHelper, UIWidget): |
class UIForm(UIHelper): |
914 |
tabStyles = {'left':wxNB_LEFT, |
tabStyles = {'left':wxNB_LEFT, |
915 |
'right':wxNB_RIGHT, |
'right':wxNB_RIGHT, |
916 |
'bottom':wxNB_BOTTOM, |
'bottom':wxNB_BOTTOM, |
922 |
self.__ui = event.ui |
self.__ui = event.ui |
923 |
self.__ui.__notebookLoopTrap = 0 |
self.__ui.__notebookLoopTrap = 0 |
924 |
|
|
925 |
if object.tabbed: |
if object._layout.tabbed: |
926 |
tabstyle =self.tabStyles[object.tabbed] |
tabstyle =self.tabStyles[object._layout.tabbed] |
927 |
newWidget = wxNotebook(event.container,-1,wxPoint(10,10), |
newWidget = wxNotebook(event.container,-1,wxPoint(10,10), |
928 |
size=event.interface.mainWindow.panel.GetClientSize(), |
size=event.interface.mainWindow.panel.GetClientSize(), |
929 |
style=tabstyle) |
style=tabstyle) |
930 |
newWidget.Show(TRUE) |
newWidget.Show(TRUE) |
931 |
EVT_NOTEBOOK_PAGE_CHANGING(newWidget, newWidget.GetId(), self.notebookTabHandler) |
|
932 |
|
# Note: EVT_NOTEBOOK_PAGE_CHANGING does't return the selected page on win32 |
933 |
|
EVT_NOTEBOOK_PAGE_CHANGED(newWidget, newWidget.GetId(), self.notebookTabHandler) |
934 |
|
|
935 |
event.interface._notebook = newWidget |
event.interface._notebook = newWidget |
936 |
else: |
else: |
944 |
return newWidget |
return newWidget |
945 |
|
|
946 |
def notebookTabHandler(self,event): |
def notebookTabHandler(self,event): |
947 |
if event.GetEventType() == wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING: |
if event.GetEventType() == wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED: |
948 |
|
object = _IdToGFObj[_eventObjTowxWindow(event).GetId()] |
949 |
|
|
950 |
action = None |
action = None |
951 |
|
|
952 |
if self.__ui.__notebookLoopTrap == 0: |
if sys.platform == 'win32': |
953 |
action = events.Event('requestPAGE',event.GetSelection()) |
if self.__ui.__notebookLoopTrap == 1: |
954 |
self.__ui.__notebookLoopTrap = 1 |
action = events.Event('requestPAGE',event.GetSelection(), _form=object) |
955 |
|
self.__ui.__notebookLoopTrap = 0 |
956 |
|
else: |
957 |
|
self.__ui.__notebookLoopTrap = 1 |
958 |
else: |
else: |
959 |
self.__ui.__notebookLoopTrap = 0 |
if self.__ui.__notebookLoopTrap == 0: |
960 |
|
action = events.Event('requestPAGE',event.GetSelection(), _form=object) |
961 |
|
if WXVERSION < '2.3': |
962 |
|
self.__ui.__notebookLoopTrap = 1 |
963 |
|
else: |
964 |
|
self.__ui.__notebookLoopTrap = 0 |
965 |
|
|
966 |
if action: |
if action: |
967 |
self._eventHandler(action) |
self._eventHandler(action) |
968 |
|
event.Skip() |
969 |
##################################################################### |
##################################################################### |
970 |
## |
## |
971 |
## Required Dialog box support |
## Required Dialog box support |
1000 |
message = lineWrap(message,60) |
message = lineWrap(message,60) |
1001 |
wxMessageDialog.__init__(self, interface, message, caption, style=wxOK|wxICON_EXCLAMATION) |
wxMessageDialog.__init__(self, interface, message, caption, style=wxOK|wxICON_EXCLAMATION) |
1002 |
|
|
|
|
|
|
# |
|
|
# UIGenericBox |
|
|
# |
|
|
# A generic box providing feedback info |
|
|
# |
|
|
class UIGenericBox(wxDialog, UIHelper): |
|
|
def __init__(self, interface, caption): |
|
|
self.interface = interface |
|
|
self.caption = caption |
|
|
|
|
|
def createGenericBox(self, message, buttonSet): |
|
|
self.genericBox = dlg = wxDialog(self.interface, -1, self.caption) |
|
|
buttonCount = len(buttonSet) |
|
|
|
|
|
dlg.SetAutoLayout(true) |
|
|
|
|
|
#bmp = wxImage(images_dir+gConfig('smallPNG'), wxBITMAP_TYPE_PNG).ConvertToBitmap() |
|
|
|
|
|
messageField = WrappedStaticText(dlg, -1, str(message), 300, style=wxALIGN_CENTER) |
|
|
|
|
|
dlgWidth = messageField.GetSize().GetWidth() + 30 |
|
|
|
|
|
dlgHeight = messageField.GetSize().GetHeight() + 80 |
|
|
|
|
|
idx = 0 |
|
|
buttonSetWidth = 0 |
|
|
maxButtonHeight = 0 |
|
|
button = [] |
|
|
|
|
|
for buttonLabel in buttonSet: |
|
|
buttonId = wxNewId() |
|
|
button.append(wxButton(dlg,buttonId,_(buttonLabel))) |
|
|
EVT_BUTTON(dlg, buttonId, lambda event, s=self, butt=idx+1: s.setResult(butt) ) |
|
|
buttonSetWidth += button[idx].GetSize().GetWidth() |
|
|
if maxButtonHeight < button[idx].GetSize().GetHeight(): |
|
|
maxButtonHeight = button[idx].GetSize().GetHeight() |
|
|
idx += 1 |
|
|
|
|
|
button[0].SetDefault() |
|
|
dlgWidth = max(dlgWidth, buttonSetWidth + 15 * (buttonCount- 1) + 40) |
|
|
|
|
|
dlgHeight += maxButtonHeight - 6 |
|
|
|
|
|
# Create and position the logo |
|
|
#wxStaticBitmap(dlg,-1, bmp, |
|
|
# wxPoint((dlgWidth-bmp.GetWidth())/2, 12), |
|
|
# wxSize(bmp.GetWidth(), bmp.GetHeight())) |
|
|
|
|
|
# Move the various widgets into position |
|
|
messageField.SetPosition( |
|
|
wxPoint(dlgWidth/2 - messageField.GetSize().GetWidth()/2, |
|
|
30 )) |
|
|
idx = 0 |
|
|
incr = (dlgWidth - 40 - buttonSetWidth) |
|
|
if buttonCount > 1: |
|
|
incr = incr / (buttonCount - 1) |
|
|
|
|
|
if buttonCount > 1: |
|
|
currentX = 15 |
|
|
else: |
|
|
currentX = (dlgWidth - buttonSetWidth) / 2 |
|
|
|
|
|
for buttonLabel in buttonSet: |
|
|
button[idx].SetPosition(wxPoint(currentX, dlgHeight - 10 - maxButtonHeight)) |
|
|
currentX += button[idx].GetSize().GetWidth() + incr |
|
|
idx += 1 |
|
|
|
|
|
dlg.SetSize(wxSize(dlgWidth, dlgHeight)) |
|
|
|
|
|
dlg.Refresh() |
|
|
dlg.Fit() |
|
|
dlg.Raise() |
|
|
dlg.CenterOnScreen() |
|
|
|
|
|
# If user cancels, this will be set to 0 |
|
|
self._result = 0 |
|
|
|
|
|
return dlg |
|
|
|
|
|
def getResult(self): |
|
|
return self._result |
|
|
|
|
|
def setResult(self, value): |
|
|
self._result = value |
|
|
self.genericBox.EndModal(1) |
|
|
self.genericBox.Destroy() |
|
|
|
|
|
|
|
1003 |
##################################################################### |
##################################################################### |
1004 |
## |
## |
1005 |
## Keymapper Support |
## Keymapper Support |
1006 |
## |
## |
1007 |
##################################################################### |
##################################################################### |
1008 |
|
from gnue.forms import GFKeyMapper |
1009 |
from gnue.forms.GFKeyMapper import vk |
from gnue.forms.GFKeyMapper import vk |
1010 |
|
|
1011 |
# Translate from wx keystrokes to our virtual keystrokes |
# Translate from wx keystrokes to our virtual keystrokes |
1048 |
def _processEvent(self,event): |
def _processEvent(self,event): |
1049 |
GDebug.printMesg(0,"uiBaseEvtHandler _processEvent was called?!?") |
GDebug.printMesg(0,"uiBaseEvtHandler _processEvent was called?!?") |
1050 |
|
|
1051 |
|
# |
1052 |
|
# mouseEvtHandler |
1053 |
|
# |
1054 |
|
# Traps most mouse events and translates them into |
1055 |
|
# GNUe events passed back to the form |
1056 |
|
# |
1057 |
class mouseEvtHandler(uiBaseEvtHandler): |
class mouseEvtHandler(uiBaseEvtHandler): |
1058 |
def __init__(self,eventProcessor): |
def __init__(self,eventProcessor): |
1059 |
eventList = [wxEVT_LEFT_DOWN] |
eventList = [wxEVT_LEFT_DOWN] |
1073 |
global _charWidth,_charHeight |
global _charWidth,_charHeight |
1074 |
object = _eventObjTowxWindow(event) |
object = _eventObjTowxWindow(event) |
1075 |
|
|
|
print object |
|
|
|
|
1076 |
id = object.GetId() |
id = object.GetId() |
1077 |
gfObject = _IdToGFObj[id] |
gfObject = _IdToGFObj[id] |
1078 |
screenWidget = _IdToWxObj[id] |
screenWidget = _IdToWxObj[id] |
1079 |
count = _IdToUIObj[id].widgets.index(screenWidget) |
count = _IdToUIObj[id].widgets.index(screenWidget) |
1080 |
|
|
1081 |
if event.GetTimestamp(): |
if event.GetTimestamp(): |
1082 |
self._eventProcessor(events.Event('requestFOCUS',gfObject)) |
self._eventProcessor('requestFOCUS',gfObject,_form=_IdToUIObj[id]._form) |
1083 |
self._eventProcessor(events.Event('requestJUMPRECORD',count - gfObject._visibleIndex)) |
self._eventProcessor('requestJUMPRECORD',count - gfObject._visibleIndex,_form=_IdToUIObj[id]._form) |
1084 |
|
|
1085 |
if isinstance(screenWidget,wxTextCtrl): |
if isinstance(screenWidget,wxTextCtrl): |
1086 |
event.SetTimestamp(0) |
event.SetTimestamp(0) |
1089 |
else: |
else: |
1090 |
textObject= wxPyTypeCast(object, 'wxTextCtrl') |
textObject= wxPyTypeCast(object, 'wxTextCtrl') |
1091 |
cursorPosition = textObject.GetInsertionPoint() |
cursorPosition = textObject.GetInsertionPoint() |
1092 |
self._eventProcessor(events.Event('requestCURSORMOVE',position=cursorPosition)) |
self._eventProcessor('requestCURSORMOVE',position=cursorPosition,_form=_IdToUIObj[id]._form) |
1093 |
|
|
1094 |
event.Skip() |
event.Skip() |
|
# if isinstance(screenWidget,wxTextCtrl): |
|
|
# event.SetTimestamp(0) |
|
|
# self.AddPendingEvent(event) |
|
|
#else: |
|
|
# textObject= wxPyTypeCast(object, 'wxTextCtrl') |
|
|
# cursorPosition = textObject.GetInsertionPoint() |
|
|
# print cursorPosition |
|
|
|
|
|
# if gfObject._type == 'GFButton': |
|
|
# self._eventProcessor(events.Event('fireTRIGGER',gfObject.trigger)) |
|
|
|
|
1095 |
|
|
1096 |
|
|
1097 |
# |
# |
1098 |
# keyboardEvtHandler |
# keyboardEvtHandler |
1099 |
# |
# |
1100 |
|
# Traps most keypress events and translates them into |
1101 |
|
# GNUe events passed back to the form |
1102 |
|
# |
1103 |
# Note: wxEVT_KEY_DOWN event seems to only return uppercase chars so |
# Note: wxEVT_KEY_DOWN event seems to only return uppercase chars so |
1104 |
# i don't trap it. |
# i don't trap it. |
1105 |
# |
# |
1125 |
not event.ControlDown() and \ |
not event.ControlDown() and \ |
1126 |
not event.AltDown() and \ |
not event.AltDown() and \ |
1127 |
int (gConfigForms('enterIsNewLine')) and \ |
int (gConfigForms('enterIsNewLine')) and \ |
1128 |
object.height > 1: |
(hasattr(object,'Char__height') and object.Char__height) > 1: |
1129 |
|
|
1130 |
command = 'NEWLINE' |
command = 'NEWLINE' |
1131 |
|
|
1154 |
action = events.Event('request%s' % command) |
action = events.Event('request%s' % command) |
1155 |
|
|
1156 |
elif object._type == 'GFButton': |
elif object._type == 'GFButton': |
1157 |
action = events.Event('fireTRIGGER',object.trigger) |
action = events.Event('buttonActivated',object) |
1158 |
|
|
1159 |
elif object.style == 'checkbox' and object._type == 'GFEntry': |
elif object.style == 'checkbox' and object._type == 'GFEntry': |
1160 |
# <space> <=> <click> |
# <space> <=> <click> |
1172 |
text=char, |
text=char, |
1173 |
code=keycode) |
code=keycode) |
1174 |
except ValueError: |
except ValueError: |
1175 |
pass #event.Skip() |
pass |
1176 |
|
|
1177 |
if action: |
if action: |
1178 |
|
# Add the object's _form to the outgoing event |
1179 |
|
# rather than every event in the function |
1180 |
|
action.__dict__.update({'_form':object._form}) |
1181 |
self._eventProcessor(action) |
self._eventProcessor(action) |
1182 |
|
|
|
##################################################################### |
|
|
## |
|
|
## Login Support |
|
|
## |
|
|
##################################################################### |
|
1183 |
|
|
1184 |
# |
# Needed by Designer (AND FORMS! :) |
|
# UILoginHandler |
|
|
# |
|
|
class UILoginHandler(GLoginHandler.LoginHandler): |
|
|
def __init__(self): |
|
|
self._wxapp = getWxApp() |
|
|
self.dlg = None |
|
|
|
|
|
def getLogin(self, loginData, errortext=None):#"Invalid username/password"): |
|
|
if 1: # TODO: This is left here to prevent me from having to unindent this code |
|
|
# TODO: Since the UI stuff is currently being gutted I'm not wasting the time |
|
|
# TODO: to do the right thing |
|
|
if len(loginData[1]): |
|
|
loginMesg = _('Login required for\n"%s"') % (loginData[1]) |
|
|
else: |
|
|
loginMesg = _('Login required for %s') % (loginData[0]) |
|
|
|
|
|
self.dlg = wxDialog(NULL, -1, _("GNU Enterprise: Login to %s") % loginData[0]) |
|
|
self.dlg.SetAutoLayout(true) |
|
|
|
|
|
bmp = wxImage(images_dir+gConfigForms('smallPNG'), wxBITMAP_TYPE_PNG).ConvertToBitmap() |
|
|
|
|
|
messageField = WrappedStaticText(self.dlg, -1, str(loginMesg), 300, style=wxALIGN_CENTER) |
|
|
|
|
|
self.textctrlList = [] |
|
|
labelList = [] |
|
|
|
|
|
dlgWidth = max(bmp.GetWidth(), messageField.GetSize().GetWidth()+20) |
|
|
|
|
|
dlgHeight = bmp.GetHeight() + messageField.GetSize().GetHeight() + 80 |
|
|
|
|
|
xSpacing = 0 |
|
|
ySpacing = 0 |
|
|
fieldLabelWidth = 0 |
|
|
|
|
|
for prompt in loginData[2]: |
|
|
s = wxStaticText(self.dlg, -1, '%s:' % prompt[1]) |
|
|
labelList.append(s) |
|
|
if prompt[2]: |
|
|
t = wxTextCtrl(self.dlg, -1,"",wxPoint(1, 1), wxSize(150, 20), |
|
|
style=wxTE_PASSWORD|wxTE_PROCESS_ENTER) |
|
|
else: |
|
|
t = wxTextCtrl(self.dlg, -1,"",wxPoint(1, 1), wxSize(150, 20), |
|
|
style=wxTE_PROCESS_ENTER) |
|
|
|
|
|
myID = len(self.textctrlList) |
|
|
self.textctrlList.append(t) |
|
|
EVT_CHAR(t, LoginFieldHandler(self, myID).loginFieldEventTrap) |
|
|
|
|
|
fieldLabelWidth = max(fieldLabelWidth, |
|
|
s.GetSize().GetWidth() + t.GetSize().GetWidth() + 10) |
|
|
|
|
|
dlgWidth = max(dlgWidth, \ |
|
|
s.GetSize().GetWidth() + t.GetSize().GetWidth() + 20) |
|
|
|
|
|
xSpacing = max(xSpacing, s.GetSize().GetWidth()) |
|
|
ySpacing = max(ySpacing, s.GetSize().GetHeight()) |
|
|
ySpacing = max(ySpacing, t.GetSize().GetHeight()) |
|
|
|
|
|
|
|
|
loginId = wxNewId() |
|
|
cancelId = wxNewId() |
|
|
|
|
|
loginButton = wxButton(self.dlg,loginId,_('Login')) |
|
|
cancelButton = wxButton(self.dlg,cancelId,_('Cancel')) |
|
|
|
|
|
EVT_BUTTON(self.dlg, loginId, self.loginButtonEventTrap) |
|
|
EVT_BUTTON(self.dlg, cancelId, self.loginCancelEventTrap) |
|
|
dlgWidth = max(dlgWidth, loginButton.GetSize().GetWidth() + |
|
|
cancelButton.GetSize().GetWidth() + 6) + 20 |
|
|
|
|
|
dlgHeight += max(loginButton.GetSize().GetHeight(), |
|
|
cancelButton.GetSize().GetHeight()) - 6 |
|
|
|
|
|
if errortext: |
|
|
errorField = WrappedStaticText(self.dlg, -1, str(errortext), 300, |
|
|
style=wxALIGN_CENTER) |
|
|
errorField.SetForegroundColour(wxColour(223,0,0)) |
|
|
|
|
|
dlgWidth = max(dlgWidth, errorField.GetSize().width+10) |
|
|
dlgHeight += errorField.GetSize().height + 6 |
|
|
|
|
|
|
|
|
firstY = bmp.GetHeight() + messageField.GetSize().GetHeight() + 50 |
|
|
lastY = firstY |
|
|
xSpacing += 10 # Add whitespace between widgets |
|
|
ySpacing += 6 # Add whitespace between widgets |
|
|
xPos = dlgWidth/2 - fieldLabelWidth/2 |
|
|
|
|
|
|
|
|
# Move the fields and labels into position |
|
|
for i in range(0, len(self.textctrlList)): |
|
|
dlgHeight = dlgHeight + ySpacing |
|
|
labelList[i].SetPosition(wxPoint(xPos, lastY)) |
|
|
self.textctrlList[i].SetPosition(wxPoint(xPos + xSpacing, lastY)) |
|
|
lastY = lastY + ySpacing |
|
|
|
|
|
if errortext: |
|
|
errorField.SetPosition( |
|
|
wxPoint(dlgWidth/2 - errorField.GetSize().width/2, |
|
|
lastY+3)) |
|
|
|
|
|
# Set the focus to the first text entry field |
|
|
self.textctrlList[0].SetFocus() |
|
|
|
|
|
# Create and position the logo |
|
|
wxStaticBitmap(self.dlg,-1, bmp, |
|
|
wxPoint((dlgWidth-bmp.GetWidth())/2, 12), |
|
|
wxSize(bmp.GetWidth(), bmp.GetHeight())) |
|
|
|
|
|
# Move the various widgets into position |
|
|
messageField.SetPosition( |
|
|
wxPoint(dlgWidth/2 - messageField.GetSize().GetWidth()/2, |
|
|
30 + bmp.GetHeight())) |
|
|
|
|
|
cancelButton.SetPosition( |
|
|
wxPoint(dlgWidth - 10 - cancelButton.GetSize().GetWidth(), |
|
|
dlgHeight - 10 - max(loginButton.GetSize().GetHeight(), |
|
|
cancelButton.GetSize().GetHeight()))) |
|
|
loginButton.SetPosition( |
|
|
wxPoint(dlgWidth - 16 - cancelButton.GetSize().GetWidth() - \ |
|
|
loginButton.GetSize().GetWidth(), |
|
|
dlgHeight - 10 - max(loginButton.GetSize().GetHeight(), |
|
|
cancelButton.GetSize().GetHeight()))) |
|
|
|
|
|
self.loginButton = loginButton |
|
|
|
|
|
self.dlg.SetSize(wxSize(dlgWidth, dlgHeight)) |
|
|
|
|
|
self.dlg.Refresh() |
|
|
self.dlg.Fit() |
|
|
self.dlg.Raise() |
|
|
self.dlg.CenterOnScreen() |
|
|
|
|
|
# If user cancels, this will be set to 0 |
|
|
self._completed = 0 |
|
|
self.dlg.ShowModal() |
|
|
|
|
|
if not self._completed: |
|
|
raise GLoginHandler.UserCanceledLogin |
|
|
|
|
|
rv = {} |
|
|
for i in range(0, len(loginData[2])): |
|
|
rv[loginData[2][i][0]] = self.textctrlList[i].GetValue() |
|
|
|
|
|
return rv |
|
|
|
|
|
# |
|
|
# Login is completed, for whatever reason |
|
|
# |
|
|
def loginCompleted(self, successful): |
|
|
self._completed = successful |
|
|
self.dlg.EndModal(1) |
|
|
|
|
|
# |
|
|
# Called when user clicks "login" |
|
|
# |
|
|
def loginButtonEventTrap(self, event): |
|
|
self.loginCompleted(1) |
|
|
|
|
|
# |
|
|
# Called when user clicks "cancel" |
|
|
# |
|
|
def loginCancelEventTrap(self, event): |
|
|
self.loginCompleted(0) |
|
|
|
|
|
# |
|
|
# TODO: This is a hack required because windows |
|
|
# TODO: seems to have issues with wxWindows dialogs |
|
|
# |
|
|
def destroyLoginDialog(self): |
|
|
self.dlg.Destroy() |
|
|
|
|
|
# |
|
|
# LoginFieldHandler |
|
|
# |
|
|
# Used by the login handler |
|
|
# enables the user to press return and have it jump to the next box |
|
|
# |
|
|
class LoginFieldHandler: |
|
|
def __init__(self, app, seq): |
|
|
self.app = app |
|
|
self.seq = seq |
|
|
|
|
|
def loginFieldEventTrap(self, event): |
|
|
if event.KeyCode() in (WXK_RETURN, WXK_TAB): |
|
|
if self.seq < len(self.app.textctrlList) - 1: |
|
|
self.app.textctrlList[self.seq+1].SetFocus() |
|
|
else: |
|
|
if event.KeyCode() == WXK_TAB: |
|
|
if event.ShiftDown(): |
|
|
self.app.textctrlList[self.seq-1].SetFocus() |
|
|
else: |
|
|
self.app.loginButton.SetFocus() |
|
|
else: |
|
|
self.app.loginCompleted(1) |
|
|
else: |
|
|
event.Skip() |
|
|
|
|
|
|
|
|
|
|
|
class WrappedStaticText(wxStaticText): |
|
|
def __init__(self, parent, id, label, width, *args, **params): |
|
|
wxStaticText.__init__(self, parent, id, "bah!", *args, **params) |
|
|
|
|
|
|
|
|
textSoFar = "" |
|
|
thisLine = "" |
|
|
for part in string.split(label,'\n'): |
|
|
for word in string.split(part): |
|
|
self.SetLabel(thisLine + word) |
|
|
if self.GetSize().width > width: |
|
|
textSoFar += thisLine + " \n" |
|
|
thisLine = word + " " |
|
|
else: |
|
|
thisLine += word + " " |
|
|
|
|
|
textSoFar += thisLine + " \n" |
|
|
thisLine = "" |
|
|
|
|
|
if len(textSoFar): |
|
|
self.SetLabel(string.replace(textSoFar,' \n','\n')[:-1]) |
|
|
else: |
|
|
self.SetLabel("") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Needed by Designer |
|
1185 |
WIDGETS = {'GFLabel' : UILabel, |
WIDGETS = {'GFLabel' : UILabel, |
1186 |
'GFBox' : UIBox, |
'GFBox' : UIBox, |
1187 |
'GFPage' : UIPage, |
'GFPage' : UIPage, |
1189 |
'GFEntry' : UIEntry, |
'GFEntry' : UIEntry, |
1190 |
'GFButton' : UIButton, |
'GFButton' : UIButton, |
1191 |
'GFScrollBar' : UIScrollBar, |
'GFScrollBar' : UIScrollBar, |
1192 |
'GFMainToolBar': UIMainToolBar, |
} |
|
'GFMainMenuBar': UIMainMenuBar, |
|
|
} |
|
|
|
|
|
|
|
|
# Shortcut |
|
|
images_dir = GConfig.getInstalledBase('forms_images','common_images') + '/' |
|
|
|
|
|
|
|