commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r9451 - in trunk/gnue-forms/src/uidrivers/html: . widgets


From: jan
Subject: [gnue] r9451 - in trunk/gnue-forms/src/uidrivers/html: . widgets
Date: Wed, 28 Mar 2007 07:17:11 -0500 (CDT)

Author: jan
Date: 2007-03-28 07:17:10 -0500 (Wed, 28 Mar 2007)
New Revision: 9451

Added:
   trunk/gnue-forms/src/uidrivers/html/GFController.py
   trunk/gnue-forms/src/uidrivers/html/gnue.js
Modified:
   trunk/gnue-forms/src/uidrivers/html/GFServer.py
   trunk/gnue-forms/src/uidrivers/html/GFhtmlApp.py
   trunk/gnue-forms/src/uidrivers/html/Generator.py
   trunk/gnue-forms/src/uidrivers/html/ToolBar.py
   trunk/gnue-forms/src/uidrivers/html/UIdriver.py
   trunk/gnue-forms/src/uidrivers/html/widgets/entry.py
   trunk/gnue-forms/src/uidrivers/html/widgets/form.py
Log:
update forms webfrontend to new version
   - add threaded controller object
   - moved javascript code into file
   - switch to dojo 4.2
   - various other changes


Added: trunk/gnue-forms/src/uidrivers/html/GFController.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/GFController.py 2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/GFController.py 2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -0,0 +1,319 @@
+#
+# 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 2000-2007 Free Software Foundation
+#
+# FILE:
+# uidrivers/html/GFServer.py
+#
+# DESCRIPTION:
+#
+# NOTES:
+
+import pickle
+import Queue
+import threading, thread
+
+from gnue.common import events
+
+from UISplashScreen import SplashScreen
+from gnue.forms.GFInstance import GFInstance
+from gnue.common.apps import GConfig, errors
+from gnue.forms.uidrivers.html.common import textEncode, textDecode
+import Generator
+
+
+# =============================================================================
+# GNUe Forms HTML UI driver -- Session (contains one instance)
+# =============================================================================
+
+class gnueSession:
+    '''
+    Each Session is represented by a gnueSession object. A session holds the 
following
+    variables:
+       identifier     - session id
+       backend_state  - one of (0=idle, 1=hasContenttoDeliver, 
2=willshortlyDeliverContent,
+                                3=waiting_for_additional_request, 
4=shutting_down
+
+       new HTML request will be delayed for a short time,
+
+    '''
+    IDLE_STATE = 0
+    LOADING_STATE = 1
+    BUSY_STATE = 2
+    WILL_DELIVER = 3
+    LATE_DELIVERY = 4
+    SHUTTING_DOWN = 9
+
+    instance = None
+    # split updates between different forms
+    _updates = []
+    _state = LOADING_STATE
+
+    _max_session_threads = 3 # maximum number of threads allowed to be 
executed in the backend in parallel
+
+    def __init__(self, controller, id):
+        assert gDebug (4, "Creating new session")
+        self._id=id
+        self._controller = controller
+        self._state_lock = threading.Lock()
+        self._update_lock = threading.Lock()
+        self._usageCounter = threading.Semaphore(self._max_session_threads)
+
+        # is just one event sufficient ?
+        # TODO: check, What happens if two requests come in in parallel?
+        # use a per thread event instead?
+        self.updates_available = threading.Event()
+
+    def setup(self, baseform, userParameters):
+
+        # Create the instance that will control the loaded form(s) for this 
session
+        assert gDebug (4, "Creating GFInstance object")
+        # HACK: there should be a better way to get ui and connection object
+        gfclient=self._controller.gfclient
+
+        self.instance = GFInstance (self, gfclient.connections, gfclient._ui,
+                                    False, userParameters)
+
+        # Assign the proper login handler based upon the user interface choice
+        # TODO: we need a login handler per session! How can we achieve this?
+        # by separate connection pools?
+        loginHandler = gfclient._ui.UILoginHandler ()
+        loginHandler.uiDriver = self.instance._uiinstance
+        gfclient.getConnectionManager ().setLoginHandler (loginHandler)
+
+        # disable standart html drivers mainloop
+        gfclient._ui.GFhtmlApp.GFhtmlApp._mainLoop = 1
+
+        self.instance.run_from_file(baseform, None)
+        self._setState(self.IDLE_STATE)
+        print "GNUe Forms Session %s setup" % self._id
+
+        assert gLeave (4)
+
+    def executeCmd(self, cmd, args):
+
+        assert self.instance != None
+        if self.getState()==self.SHUTTING_DOWN:
+            pass
+
+        self._usageCounter.acquire()
+
+        self._setState(self.WILL_DELIVER)
+
+        updates=[]
+
+        try:
+
+            if cmd == "event":
+                # id = int(args["id"])
+                event = args["event"]
+                e = events.Event(event, \
+                     _form=self.instance._main_form)
+                self.instance.dispatchEvent(e)
+
+            elif cmd == "onChange":
+                id = int(args["id"])
+                text = args["text"]
+
+                gfObject = self.instance._uiinstance._WidgetToGFObj [id]
+                e = events.Event('requestREPLACEVALUE', text = text, \
+                     _form=self.instance._main_form)
+                self.instance.dispatchEvent(e)
+
+
+            elif cmd == "onFocus":
+                id = int(args["id"])
+                UIObject = self.instance._uiinstance._WidgetToUIObj [id]
+                widget = self.instance._uiinstance._IdToWidget [id]
+                UIObject._focusInHandler (id)
+
+            elif cmd == "btn":
+                id = int(args["id"])
+
+                gfObject = self.instance._uiinstance._WidgetToGFObj [id]
+                gfObject._event_fire ()
+
+            else:
+                updates = [["status","","This session is invalid. Please 
restart!"]]
+        except Exception, e:
+            updates = [["alert","","Error %s" % e]]
+
+        # refresh updates
+        updates.extend(self.instance._uiinstance._UIform.get_updates())
+        print "pushing updates %s" % updates
+        self._pushUpdates(updates)
+        self.updates_available.set()  # inform listeners, that new updates are 
available
+        self.updates_available.clear()
+        self._usageCounter.release()
+
+    def getHtml(self, form):
+        if self._state==self.LOADING_STATE:
+            return Generator.build_loading_page("Please wait until loaded")
+        else:
+            # FIXME: do we need to acquire a semaphore here?
+            self._usageCounter.acquire()
+            html =  self.instance._uiinstance._UIform.get_html()
+            self._usageCounter.release()
+            return html
+
+    def getState(self):
+        return self._state
+
+    def fetchUpdates(self):
+        self._update_lock.acquire()
+        updates = self._updates
+        self._updates = []
+        print "getting updates %s" % updates
+        self._update_lock.release()
+        return updates
+
+    def _setState(self, state):
+        self._state_lock.acquire()
+        self._state=state
+        self._state_lock.release()
+
+    def _pushUpdate(self, update):
+        self._update_lock.acquire()
+        self._updates.append(update)
+        self._update_lock.release()
+
+    def _pushUpdates(self, updates):
+        self._update_lock.acquire()
+        self._updates.extend(updates)
+        self._update_lock.release()
+
+class backendThread ( threading.Thread ):
+    '''
+    This type of thread is changeing gnue forms and executing specific actions.
+
+    It is different from the frontendthread (as started by the webserver) that 
it
+    will just trigger actions. The task of the frontendthread is pass commands 
from
+    the client to the backendthread and to check if any UI updates or UI 
commands should be
+    passed back to the frontend.
+    '''
+    shutdown = False
+    job_pool = None
+
+    def run ( self ):
+
+        while not self.shutdown:
+            job = self.job_pool.get()
+
+            if job != None:
+                print "Doing backendJob %s" % job
+                job[0].executeCmd(job[1],job[2])
+                print "Job done: %s" % job
+
+# =============================================================================
+# GNUe Forms HTML UI driver -- ComController (Singleton pattern)
+# =============================================================================
+
+
+class ComController:
+    '''
+    This controller should control how the incoming request from the web app 
are computed.
+
+    A list of commands should require the form to wait for an answer and not 
allow further commands or
+    input. At least Commit, Search, ... should have this behavior.
+
+    # todo: add garbage collector,  add session time out to each session
+
+    '''
+
+    __single = None
+
+    max_threads = 2
+    threads = []    # create threadpool to handle jobs
+    backend_jobs = None
+
+    sessions = {}        # create sessions
+    base_form = ""
+
+    def __init__( self ):
+        """
+        """
+        # Singleton pattern
+        if ComController.__single:
+            raise ComController.__single
+        ComController.__single = self
+
+        # create queue to transfer data to backend tasks
+        self.backend_jobs = Queue.Queue ( 0 )
+
+        # TODO: convert fixed size threadpool into dynamic pool, i.e. just 
startup threads if required
+        x=0
+        while x<self.max_threads:
+            x+=1
+            th=backendThread()
+            self.threads.append(th)
+            th.setName("Backend_%s" % x)
+            th.job_pool = self.backend_jobs
+            th.start()
+
+    def pullHtml(self, session_id, form):
+        if not self.sessions.has_key(session_id):
+            return Generator.build_error_page("restart", "Wrong session or 
Session timed out!")
+
+        # TODO: get_html call should be thread safe and shouldn't change 
anything
+        if form=="base":
+            response=Generator.build_basic_dialog()
+        else:
+            return self.sessions[session_id].getHtml(form)
+
+        return response
+
+
+    def handleRequest(self, session_id, command, arguments):
+        if not self.sessions.has_key(session_id):
+            return  [["status","","This session is invalid. Please restart!"]]
+
+        # TODO: check for health of thread pool, and if necessary startup new 
threads or print warning
+        print "processing %s - %s" % (command, arguments)
+        self.backend_jobs.put([self.sessions[session_id], command, arguments])
+        self.sessions[session_id].updates_available.wait(5)  # 5 sec
+        # return results
+        return self.pullCommands(session_id)
+
+
+    def pullCommands(self, session_id):
+        return self.sessions[session_id].fetchUpdates()
+
+    def startSession(self, session_id, params):
+        self.sessions[session_id] = gnueSession(self, session_id)
+
+        # TODO make setup to backendtasks
+        self.sessions[session_id].setup(self.base_form, params)
+        # self.backend_jobs.put([self.sessions[session_id], "setup"]
+
+
+    def delSession(self, session_id):
+        # TODO check for still working tasks, use locking
+        del self.sessions[session_id]
+        # self.gfclient.getConnectionManager ().closeAll ()
+
+    def shutdown(self, urgency):
+        '''
+
+        @param urgency: 0=high (System will shutdown at once t<10sec)
+                        1=standart (normal shutdown)
+                        2=low (system will not accept new clients, but will 
shutdown
+        '''
+
+        for th in threads:
+            th.shutdown=True


Property changes on: trunk/gnue-forms/src/uidrivers/html/GFController.py
___________________________________________________________________
Name: svn:executable
   + *

Modified: trunk/gnue-forms/src/uidrivers/html/GFServer.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/GFServer.py     2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/GFServer.py     2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -32,7 +32,6 @@
 from gnue.common.utils.uuid import UUID
 from BaseHTTPServer import HTTPServer
 from SocketServer import ThreadingMixIn
-from gnue.common.apps.GClientApp import StartupError
 
 from gnue.common import events
 
@@ -40,7 +39,10 @@
 from gnue.forms.GFInstance import GFInstance
 from gnue.common.apps import GConfig, errors
 from gnue.forms.uidrivers.html.common import textEncode, textDecode
+from Generator import build_basic_dialog
 
+from GFController import ComController
+
 from types import UnicodeType
 
 try:
@@ -50,8 +52,10 @@
     raise ImportError
 
 _iconpath = GConfig.getInstalledBase('form_images', 'common_images')
-_includepath = gConfigForms("htmlui_include_path")
+_includepath = 
os.path.join(GConfig.getInstalledBase('common_shared'),'webfrontend')
+_gnuejs_path = os.path.dirname(__file__)
 
+
 class ThreadingHTTPServer (ThreadingMixIn, HTTPServer):
     pass
 
@@ -65,9 +69,17 @@
     def __init__(self, gfclient):
         self.splash = SplashScreen()
         self.instances = {}
-        self.gfclient = gfclient
+        # self.gfclient = gfclient
         self.jsonenc = JSONEncoder()
+        self._controller = ComController()
+        self._controller.gfclient=gfclient
 
+        # assign form file from 1st free argument
+        if len (gfclient.ARGUMENTS):
+            self._controller.base_form = gfclient.ARGUMENTS [0]
+        else:
+            raise StartupError, u_("No Forms Definition File Specified.")
+
     def serve(self):
         print '\nGNUe Forms HTML UI driver is loaded.'
         print '\n-- please point your browser to http://127.0.0.1:8000 --'
@@ -75,116 +87,21 @@
         server.GFServer = self
         server.serve_forever()
 
-    def createFormsInstance(self, uid, userParameters):
 
-        # Create the instance that will control the loaded form(s)
-        assert gDebug (4, "Creating GFInstance object")
+    # TODO: overwrite finalizeRequest to pass more data (controller object) to 
Requesthandler
 
-        instance = GFInstance (self, self.gfclient.connections, 
self.gfclient._ui,
-                               self.gfclient.disableSplash, userParameters)
+    # TODO: remove the following commands from here and directly call 
controller object
 
-        self.instances[uid]=instance
+    def createFormsInstance(self, id, userParameters):
+        self._controller.startSession(id, userParameters)
 
-        # Assign the proper login handler based upon the user interface choice
-        #FIXME: IMHO, it would be much better if the login handler would be 
just a
-        # function, which could be a method of the GFUserInterfae object - much
-        # like _showException.  -- Reinhard
-        loginHandler = self.gfclient._ui.UILoginHandler ()
-        loginHandler.uiDriver = instance._uiinstance
-        self.gfclient.getConnectionManager ().setLoginHandler (loginHandler)
+    def displayFormsInstance(self, uuid, form):
+        return self._controller.pullHtml(uuid, form)
 
-        # assign form file from 1st free argument
-        if len (self.gfclient.ARGUMENTS):
-            formfile = self.gfclient.ARGUMENTS [0]
-
-        else:
-            basename = os.path.basename (sys.argv [0])
-
-            # If no form specified, then see if this is a symlinked form 
definition
-            if not basename.lower ().split ('.') [0] in ('gnue-forms', 
'gfclient'):
-                formfile = os.path.join (
-                  GConfig.getInstalledBase ('forms_appbase', 'common_appbase',
-                                            'install_prefix'),
-                  gConfigForms ('FormDir'), basename + ".gfd")
-            else:
-                raise StartupError, u_("No Forms Definition File Specified.")
-
-        # disable standart html drivers mainloop
-        self.gfclient._ui.GFhtmlApp.GFhtmlApp._mainLoop = 1
-
-        instance.run_from_file(formfile, None)
-        instance.activate ()
-
-        print "GNUe Forms Session %s started" % uid
-
-        assert gLeave (4)
-
-    def displayFormsInstance(self,uuid):
-        # TODO: thread safety: allow only one access to a
-        #       specific instance at one time
-        if self.instances.has_key(uuid):
-            response=self.instances[uuid]._uiinstance._UIform.get_html()
-        else:
-            response="""<HTML><HEAD></HEAD><BODY>
-            <H1>Wrong Session or Session timed out!</H1><BR>
-            <A HREF="/">Restart GNUe Forms</A></BODY></HTML>
-            """
-
-        return response
-
     def executeCmd(self, uuid, cmd, args):
+        return self._controller.handleRequest(uuid, cmd, args)
 
-        # TODO: thread safety: allow only one access to a
-        #       specific instance at one time
-        if cmd == "" or not self.instances.has_key(uuid):            
-            updates = [["status","","This session is invalid. Please 
restart!"]]
-            
-        elif cmd == "event":
-            # id = int(args["id"])
-            event = args["event"]
-            e = events.Event(event, \
-                 _form=self.instances[uuid]._main_form)
-            self.instances[uuid].dispatchEvent(e)
-            updates = self.instances[uuid]._uiinstance._UIform.get_updates()
-            # updates.append(["alert","","Menuitem clicked"])
-        elif cmd == "onChange":
-            id = int(args["id"])
-            text = args["text"]
 
-            gfObject = self.instances[uuid]._uiinstance._WidgetToGFObj [id]
-            e = events.Event('requestREPLACEVALUE', text = text, \
-                 _form=self.instances[uuid]._main_form)
-            self.instances[uuid].dispatchEvent(e)
-            updates = self.instances[uuid]._uiinstance._UIform.get_updates()
-
-        elif cmd == "onFocus":
-            id = int(args["id"])
-            UIObject = self.instances[uuid]._uiinstance._WidgetToUIObj [id]
-            widget = self.instances[uuid]._uiinstance._IdToWidget [id]
-            UIObject._focusInHandler (id)
-
-            updates = self.instances[uuid]._uiinstance._UIform.get_updates()
-
-        elif cmd == "btn":
-            id = int(args["id"])
-
-            gfObject = self.instances[uuid]._uiinstance._WidgetToGFObj [id]
-            gfObject._event_fire ()
-                        
-            updates = self.instances[uuid]._uiinstance._UIform.get_updates()
-            
-        else:
-            updates = []
-
-        return self.jsonenc.encode(updates)
-
-    def removeFormsInstance(self, uuid):
-        assert gDebug (4, "Closing all connections")
-        # FIXME: close all connections for the instance self.instances[uid]
-        # self.gfclient.getConnectionManager ().closeAll ()
-        del self.instances[uuid]
-
-
 # =============================================================================
 # GNUe Forms HTML UI driver Request handler
 # =============================================================================
@@ -212,20 +129,23 @@
         try:
             if self.path=="/":
                 uuid = UUID.generate_random ()
-                forward_url = "session_%s.htm" % uuid
+                forward_url = "session_%s/index.html" % uuid
                 response = self.server.GFServer.splash.get_html(forward_url)
                 self.push_content(response)
                 self.server.GFServer.createFormsInstance(uuid, {})
-    
+
             elif self.path=="/splashscreen.png":
                 response = self.server.GFServer.splash.getPicture()
                 self.push_content(response,"image/png")
-    
-            elif self.path[0:9]=="/session_" and self.path[41:]==".htm":
+
+            # FIXME: distinguish between different forms of one session here
+            elif self.path[0:9]=="/session_" and self.path[41]=="/" and \
+                 self.path[-5:]==".html":
                 uuid=self.path[9:41]
-                response=self.server.GFServer.displayFormsInstance(uuid)
+                formname=self.path[42:-5]
+                response=self.server.GFServer.displayFormsInstance(uuid, 
formname)
                 self.push_content(response)
-    
+
             elif self.path[0:9]=="/jsonrpc_" and self.path[41:42]=="?":
                 uuid=self.path[9:41]
                 # FIXME: Use standart argument parser
@@ -235,24 +155,39 @@
                 for i in arg_list:
                     z=i.split('=')
                     args[z[0]]=unquote(z[1]).decode("utf-8")
-    
+
                 try:
                     cmd=args['cmd']
                 except:
                     cmd=""
-    
-                response = self.server.GFServer.executeCmd(uuid,cmd,args)
+
+                try:
+                    response = self.server.GFServer.executeCmd(uuid,cmd,args)
+                except:
+                    (group, name, message, detail) = errors.getException()
+                    message = u"""<HTML><HEAD></HEAD><BODY><H1>Exception 
occured!</H1>
+                        Group: %s<BR>
+                        Name: %s<BR>
+                        Message: %s<BR>
+                        Details: <BR><PRE>%s</PRE></BODY></HTML>
+                        """ % (group, name, message, detail)
+                    response = [["alert","Warning!",message]]
+                response = self.server.GFServer.jsonenc.encode(response)
                 self.push_content(response,"text/text")
                 print "JSON: %s -> %s" % (self.path,response)
-    
+
+            # get gnue specific js file from source directory
+            elif self.path=="/incl/gnue.js":
+                self.deliver_file(_gnuejs_path, 'gnue.js')
+
             # Include file handling for libraries
             elif self.path[0:6]=="/incl/":
-                self.deliver_file(_includepath, self.path[6:])            
-                    
+                self.deliver_file(_includepath, self.path[6:])
+
             # file handling for icons
             elif self.path[0:6]=="/icon/":
                 self.deliver_file(_iconpath, self.path[6:])
-    
+
             else:
                 self.send_response(404)
                 self.connection.shutdown (1)
@@ -267,21 +202,21 @@
             Details: <BR><PRE>%s</PRE></BODY></HTML>
             """ % (group, name, message, detail)
             self.push_content(message)
-            print textDecode(message)
-          
+            print textEncode(message)
+
         # If a shutdown of the connection is requested do so, although we 
assume to
         # have a persistent connection.
         if self.close_connection:
             self.connection.shutdown (1)
-            
+
     def deliver_file(self, base, path):
-        
+
         # FIXME: implement security measures:
         #        1: normalize path
         #        2: remove all ".."
         #
         realpath=os.path.join(base, path)
-        
+
         if realpath[-3:]==".js":
             mimetype = "text/javascript"
         elif realpath[-4:]==".css":
@@ -314,10 +249,10 @@
                 print " the install path to gnue.conf: 'htmlui_include_path = 
<path>'"
                 print " Currently searching for dojo.js at: '%s' " % realpath
                 print 
"****************************************************************"
-            
+
     def push_content(self, response, content_type="text/html"):
         if type(response)==UnicodeType:
-            # FIXME: Should local encoding be used? 
+            # FIXME: Should local encoding be used?
             response = response.encode('utf-8')
 
         self.send_response (200, flush = False)

Modified: trunk/gnue-forms/src/uidrivers/html/GFhtmlApp.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/GFhtmlApp.py    2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/GFhtmlApp.py    2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -76,7 +76,7 @@
 
     def quit(self):
         self.running=False
-        sys.exit()
+        # sys.exit()
 
 def textEncode(a):
     return a
\ No newline at end of file

Modified: trunk/gnue-forms/src/uidrivers/html/Generator.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/Generator.py    2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/Generator.py    2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -28,93 +28,108 @@
 def _on_click_event(event):
     return u' onClick="sendCmd(\'event\',\'event=%s\');"' % event
 
-def _on_change_event(id):
-    return u'onchange="sendCmd(\'onChange\',\'id=%s&text=\'+this.value)"\n' % 
id
+def _on_change_event(id, what):
+    return u'onchange="sendCmd(\'onChange\',\'id=%s&text=\'+this.%s)"\n' % 
(id, what)
 
-def _on_focus_event(id):
-    return u'onfocus="sendCmd(\'onFocus\',\'id=%s&text=\'+this.value)"\n' % id
+def _on_focus_event(id, what):
+    return u'onfocus="sendCmd(\'onFocus\',\'id=%s&text=\'+this.%s)"\n' % (id, 
what)
 
 def _css_position(x,y,width,height):
     return (u'style="position:absolute; top:%spx; left:%spx;'+\
             u' width:%spx; height:%spx;"') % (FIX + y, x, width, height)
 
-def build_label(id, value, x, y, width, height):  
+def build_tooltip(forid, text):
+    return (u'<span dojoType="tooltip" connectId="%s" caption="%s" 
toggle="fade" '+\
+            u'toggleDuration="500"></span>\n') % (forid, text)
+
+def build_label(id, value, x, y, width, height):
     return (u'<div id="%s" %s>%s</div>\n') % \
-           (id, _css_position(x,y,width,height-FIX2), value)  
-            
-def build_entry_label(id, value, x, y, width, height):  
+           (id, _css_position(x,y,width,height-FIX2), value)
+
+def build_entry_label(id, value, x, y, width, height):
     return (u'<div id="%s" %s>%s</div>\n') % \
-           (id, _css_position(x,y,width,height-FIX2), value)    
-           
-def build_entry_checkbox(id, value, label, x, y):  
+           (id, _css_position(x,y,width,height-FIX2), value)
+
+def build_entry_checkbox(id, value, label, x, y):
     return (u'<div style="position:absolute; top:%spx; left:%spx">\n'+\
             u'<input type="checkbox" id="%s" dojoType="Checkbox" value="%s" %s 
%s/>\n'+\
             u'<label for="%s">%s</label></div>\n') % \
-           (FIX + y, x, id, value, _on_change_event(id),
-            _on_focus_event(id), id, label) 
-           
-def build_entry_default(id, value, x, y, width, height):
-    return u'<input type="text" id="%s" value="%s" %s\n %s\n %s/>\n' % \
-           (id, value, _css_position(x,y,width,height-FIX2), \
-           _on_change_event(id),_on_focus_event(id))
-           
+           (FIX + y, x, id, value, _on_change_event(id,"value"),
+            _on_focus_event(id, "value"), id, label)
+
+def build_entry_default(id, value, x, y, width, height, textbox_style):
+    return (u'<div %s><input dojo:type="%s" type="text" id="%s" value="%s"\n 
%s\n %s ' +\
+            u'dojoOnBuild="fixCSS(this);"/></div>\n') % \
+           (_css_position(x,y,width,height-FIX2),textbox_style, id, value,  \
+           _on_change_event(id,"textbox.value"),_on_focus_event(id, 
"textbox.value"))
+    # dojo:type="Textbox", IntegerTextbox, DateTextbox, TimeTextbox
+
+
+
 def build_entry_multiline(id, value, rowcount, x, y, width, height):
     return u'<textarea id="%s" rows="%s" %s\n %s\n %s/>%s</textarea>\n' % \
            (id, rowcount, _css_position(x,y,width,height-4), \
-           _on_change_event(id),_on_focus_event(id), value)
-           
+           _on_change_event(id, "value"),_on_focus_event(id, "value"), value)
+
 def _build_choices(choices):
     out = ""
     for i in choices:
         out+=u"<option>%s</option>\n" % i
     return out
-        
+
 def build_entry_listbox(id, value, choices, rows, x, y, width, height):
     return (u'<select id="%s" value="%s" size="%s" %s\n %s\n'+ \
             u'%s>\n%s</select>\n') % \
             (id, value, rows, _css_position(x,y,width,height),
-             _on_change_event(id),_on_focus_event(id), _build_choices(choices))
-            
+             _on_change_event(id, "value"),_on_focus_event(id, "value"), 
_build_choices(choices))
+
 def build_entry_combobox(id, value, choices, rows, x, y, width, height):
     return (u'<select id="%s" value="%s" size="%s" dojoType="ComboBox" %s\n 
%s\n'+ \
             u'%s>\n%s</select>\n') % \
             (id, value, rows, _css_position(x,y,width,height),
-             _on_change_event(id),_on_focus_event(id), 
_build_choices(choices))            
-                   
-def build_toolbutton(id, label, event, iconpath, tooltip, enabled):    
-    return (u'<td><button id="%s" class="Toolbutton" widgetId="%s" '+\
-            u'dojoType="Button" name="%s" %s %s>\n'+\
-            u'<img src="%s">%s\n</button></td>\n') % \
-            (id, id, label, _on_click_event(event), enabled,
-             iconpath,"") # "<br>%s" % label)
-            
-    #return '<input id="%s" type="IMAGE" name="%s" src="%s" alt="%s" %s %s/>' 
% \
-    #       (id, label, iconpath, label, _on_click_event(event), enabled)
-           
-def build_toolbar(id, content):           
-    return u'<table class="Toolbar"><tr>\n%s\n</tr></table>' % content
-    # FIXME: Use dojotype Toolbar
+             _on_change_event(id, "value"),_on_focus_event(id, "value"), 
_build_choices(choices))
 
+def _toolbar_toogle_handler(event, event2):
+    return (u'toggleItem="true" onmousedown="if (this.isSelected()) ' +\
+            u'sendCmd(\'event\',\'event=%s\'); else sendCmd(\'event\',' +\
+            '\'event=%s\');"') % (event, event2)
+
+def build_toolbar_button(id, label, event, iconpath, tooltip, toggleItem, 
enabled):
+    return (u'   <img id="%s" dojo:type="ToolbarButton" name="%s" 
dojo:icon="%s"'+\
+            u' %s %s %s />\n    %s\n') % \
+            (id, label, iconpath, enabled, _on_click_event(event), \
+             (toggleItem and _toolbar_toogle_handler(event, toggleItem) or 
""), \
+              build_tooltip(id,tooltip))
+
+
+def build_toolbar_separator(id):
+    return u'   <span dojo:type="ToolbarSeparator">&nbsp;</span>\n\n'
+
+def build_toolbar(id, content):
+    return (u'<div id="%s" dojo:type="ToolbarContainer">\n'+\
+            u'<div dojo:type="toolbar">\n%s\n</div>\n</div>\n\n') % (id, 
content)
+
 def build_button(id, label, x, y, width, height):
     return u'<input id="%s" type="button" value="%s" %s %s/>\n' % \
                 (id, label, _css_position(x,y,width,height),
                  _button_on_click(id))
-                 
-def _button_on_click(id):                 
+
+def _button_on_click(id):
     return u'onclick="sendCmd(\'btn\',\'id=%s\')"' % id
 
 def build_image(id, value, x, y, width, height):
     return u'<image id="%s" src="/images/%s" %s>' % \
            (id, value, _css_position(x,y,width,height))
-           
+
 def build_box(id, label, x, y, width, height):
-    return u'<div id="%s" %s border-width: 1px; border-style: solid">%s</div>' 
% \
+    return u'<div id="%s" %s z-index:-5; border-width: 1px; border-style: 
solid">%s</div>' % \
             (id, _css_position(x,y+FIX2,width,height-FIX)[0:-1], label)
-           
+
 def build_page(id, pagename, content):
-    return (u"<div id=\"%s\" dojoType=\"ContentPane\" label=\"%s\">\n" +\
-           u" %s \n</div>\n") % (id, pagename, content)
-           
+    return (u"<div id=\"%s\" dojoType=\"ContentPane\" label=\"%s\" " +\
+            u'onShow="sendCmd(\'pagechange\',\'page=%s&id=%s\');">\n' +\
+            u" %s \n</div>\n") % (id, pagename, pagename, id, content)
+
 def build_splashscreen(forward_url, VERSION):
     return u"""<HTML><HEAD>
 <meta http-equiv="refresh" content="4; URL=%s">
@@ -129,19 +144,94 @@
     <A HREF="%s"> Press here!</A>
    </BODY>
 </HTML>""" % (forward_url, VERSION, forward_url)
-               
+
+def build_basic_dialog():
+    return u"""<table>
+            <tr>
+                <td><h1 id="basic_title">Warning!</h1></td>
+            </tr>
+            <tr>
+                <td>&nbsp;</td>
+            </tr>
+            <tr>
+                <td id="basic_content"></td>
+            </tr>
+            <tr>
+                <td>&nbsp;</td>
+            </tr>
+            <tr>
+                <td>
+                <input type="button" id="basic_button" value="OK"></td>
+            </tr>
+        </table>
+    </form>
+"""
+
+def build_error_dialog(msg, main, error):
+    return u"""<table>
+            <tr>
+                <td>Line 1</td>
+                <td><input type="text"></td>
+            </tr>
+            <tr>
+                <td>Location:</td>
+                <td><input type="text"></td>
+            </tr>
+            <tr>
+                <td>Description:</td>
+                <td><input type="text"></td>
+            </tr>
+            <tr>
+                <td>Location:</td>
+                <td><input type="file"></td>
+            </tr>
+            <tr>
+                <td>
+                <input type="button" id="basic_button" value="OK"></td>
+            </tr>
+        </table>
+    </form>
+"""
+
+
+def build_error_page(type, message):
+    return u"""<HTML><HEAD></HEAD><BODY>
+            <H1>%s</H1><BR>
+            %s</BODY></HTML>
+            """ % (message, (type=="restart") and '<A HREF="/">Restart GNUe 
Forms</A>')
+
+def build_loading_page(message):
+    return u"""<HTML><HEAD>
+<meta http-equiv="refresh" content="4; ">
+</HEAD>
+   <BODY>
+      <CENTER>
+         <IMAGE SRC="splashscreen.png">
+         <BR>
+      </CENTER>
+    <H1 ALIGN="CENTER">%s</H1>
+   </BODY>
+</HTML>""" % (message)
+
 def build_form(title, header, pages, footer):
     #FIXME: use "labelPosition" in TabContainer
     return u"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"http://www.w3.org/TR/html4/strict.dtd";>
       <html>
       <head>
+      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+      <meta name="description" content="GNUe Forms - Interactive HTML 
Frontend" />
       <title>"""+title+"""</title>
 
       <script type="text/javascript">
-        var djConfig = {isDebug: true};
+        var djConfig = {
+               isDebug: true,
+               ieClobberMinimal : true,
+               debugAtAllCosts: true
+           };
         // djConfig.debugAtAllCosts = true;
 
       </script>
+      <script language="javascript" type="text/javascript"  
src="/incl/firebug/firebug.js"></script>
       <script type="text/javascript" src="/incl/dojo.js"></script>
       <script language="JavaScript" type="text/javascript">
         if (dojo==undefined) {
@@ -152,90 +242,12 @@
         dojo.require("dojo.widget.ContentPane")
         dojo.require("dojo.widget.TabContainer")
         dojo.require("dojo.widget.ComboBox")
+        dojo.require("dojo.widget.Toolbar")
         dojo.require("dojo.debug.console")
         dojo.require("dojo.io")
         dojo.hostenv.writeIncludes()
-
-        var updates = {}
-        var bindArgs = {
-                       url: "/jsonrpc",
-                       type: "text/javascript",
-                       load: function(type, data, evt){
-                                updates = eval(data)
-                                execUpdates()
-                             }
-        }
-        function getUid() {
-           myURL = window.location.href
-           x=myURL.indexOf("/session_")
-           return myURL.substring(x+9,x+41)
-        }
-        function sendCmd(cmd, args) {
-          bindArgs.url="/jsonrpc_"+getUid()+"?cmd="+cmd+"&"+args
-          dojo.io.bind(bindArgs);
-        }
-        function execUpdates() {
-          for (i in updates) {
-            item=updates[i];
-            try  {
-              if (item[0]=="alert") {
-                 alert(item[2])
-              }
-              if (item[0]=="status") {
-                 window.status=item[2]
-              }
-
-              if (item[0]=="set") {
-                 elem = dojo.widget.getWidgetById(item[1])
-                 if (elem==undefined) {
-                    elem = document.getElementById(item[1])
-                }
-                elem.value=item[2]
-              }
-              if (item[0]=="replace") {
-                 elem = document.getElementById(item[1])
-                 elem.innerHTML=item[2]
-              }
-              if (item[0]=="disable") {  // disable id true/false
-                 elem = dojo.widget.getWidgetById(item[1])
-                 if (elem==undefined) {
-                    elem = document.getElementById(item[1])
-                    elem.disabled=item[2];
-                 } else {
-                    elem.setDisabled(item[2])
-                 }
-               }
-               if (item[0]=="grab_focus") {
-                    elem = document.getElementById(item[1])
-                    if (elem==undefined) {
-                       elem = dojo.widget.getWidgetById(item[1])
-                       elem.focus()
-                    } else {
-                       elem.focus()
-                    }
-               }
-               if (item[0]=="set_page") {
-                    elem = dojo.widget.getWidgetById(item[2])
-                    
-               }
-               if (item[0]=="close") {
-                    // return to main page
-                    window.location="/"
-               }
-            }
-            catch(err)  {
-                   txt="There was an error on this page.\\n\\n"
-                   txt+="Id: " + item[1] + "\\n"
-                   txt+="Value: " + item[2] + "\\n"
-                   txt+="Error Name: " + err.name + "\\n"
-                   txt+="Error Message: " + err.message + "\\n\\n"
-                   txt+="Click OK to continue.\\n\\n"
-                   // err.fileName + err.lineNumber
-                   alert(txt)
-            }
-          }
-        }
       </script>
+      <script type="text/javascript" src="/incl/gnue.js"></script>
         <style>
           html, body{
           width: 100%;  /* make the body expand to fill the visible window */
@@ -253,22 +265,20 @@
         .dojoMenuBar2 {
           border-top:1px solid #d4d4d4;
         }
-        .Toolbar {
-           background-color: #85AEEC;
-           background-image:soriaBarBg.gif;
-           background-repeat:repeat-x;
-        }
-        .Toolbar .dojoButton {
-            float: left;
-            margin-right: 10px;            
-        }
-        .dojoButton .dojoButtonContents {
-             font-size: 6pt;
+        .dojoDialog {
+          background : #eee;
+          border : 1px solid #999;
+          -moz-border-radius : 5px;
+          padding : 4px;
          }
 
          </style>
       </head>
-      <body>""" + header + u"""
+      <body>
+      <a dojoType="dialog" id="basicDialog" toggle="wipe" toggleDuration="250"
+          executeScripts="true" href="base.html"></a>
+
+      """ + header + u"""
       <div dojoType="LayoutContainer"
         layoutChildPriority='top-bottom'
         style="width: 100%; height: 100%;">

Modified: trunk/gnue-forms/src/uidrivers/html/ToolBar.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/ToolBar.py      2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/ToolBar.py      2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -27,8 +27,8 @@
 #
 
 from gnue.forms.uidrivers.html.widgets._base import HtmlWidget
-from gnue.forms.uidrivers.html.common import *
-from gnue.forms.uidrivers.html.Generator import build_toolbutton, build_toolbar
+from gnue.forms.uidrivers.html.common import getNextId
+from gnue.forms.uidrivers.html.Generator import *
 from gnue.forms.uidrivers._commonGuiToolkit.ToolBar import ToolBar as 
_BaseToolBar
 from gnue.common.apps import GConfig
 
@@ -52,8 +52,13 @@
         event = 'request' + userAction.event
         label = name
         tooltip = userAction.description
+        toggleItem = userAction.canToggle
+        
+        # create correct event string, in case toolbutton can toggle
+        if toggleItem:
+            toggleItem = 'request' + toggleItem
                 
-        dhtml = build_toolbutton(id, label, event, "/icon/%s" % iconloc, 
tooltip, "%s")
+        dhtml = build_toolbar_button(id, label, event, "/icon/%s" % iconloc, 
tooltip, toggleItem, "%s")
         return ToolbarWidget(self.widget, self.driver, 'TOOLBUTTON', dhtml, id)
         
     def get_html(self):
@@ -62,7 +67,7 @@
     # Add a separator
     def addSeparator(self):
         id = getNextId()
-        dhtml = '&nbsp;&nbsp;&nbsp;&nbsp;'
+        dhtml = build_toolbar_separator(id)
         return ToolbarWidget(self.widget, self.driver, 'SEPARATOR', dhtml, id)
         
     # Enable a menu item

Modified: trunk/gnue-forms/src/uidrivers/html/UIdriver.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/UIdriver.py     2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/UIdriver.py     2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -45,16 +45,30 @@
     _WidgetToGFObj = {}
     _WidgetToUIObj = {}
     _IdToWidget = {}
+    
 
-    def initialize(self):
+    # 
---------------------------------------------------------------------------
+    # Constructor
+    # 
---------------------------------------------------------------------------
+  
+    def __init__ (self, *args, **params):
 
+        commonToolkit.GFUserInterface.__init__ (self, *args, **params)
+        self.name = "HTML"
+        # self._display = ...
+
+        # self.app = getApp ()
         self._htmlapp = gethtmlApp(self)
 
+
         self.textWidth    = 12  # The pixel width of text inside a widget
         self.textHeight   = 24  # The pixel height of text inside a widget
         self.widgetWidth  = self.textWidth  # The pixel width of a 1 char 
widget (for things like buttons)
         self.widgetHeight = self.textHeight + 5  # The pixel height of a 1 
char widget (for things like buttons)
 
+        assert gDebug (6, "Metrics %s x %s" % (self.textWidth, 
self.textHeight))
+   
+
     def mainLoop(self):
         self._htmlapp.MainLoop() # simply call the wxApp's MainLoop method
 
@@ -73,7 +87,7 @@
                   "Input routines currently not supported!"
         self._UIform._ui_show_message_(message, "", title, cancel)
         # FIXME: connect to current open form
-        return False
+        return None
         
         
     # 
---------------------------------------------------------------------------

Added: trunk/gnue-forms/src/uidrivers/html/gnue.js
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/gnue.js 2007-03-27 18:13:56 UTC (rev 
9450)
+++ trunk/gnue-forms/src/uidrivers/html/gnue.js 2007-03-28 12:17:10 UTC (rev 
9451)
@@ -0,0 +1,176 @@
+/* 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 2000-2007 Free Software Foundation
+*
+* FILE: gnue.js
+*
+* DESCRIPTION: Webfrontend specific javascript code
+*/
+
+function setCursorPosition(oInput,oStart,oEnd) {
+              if( oInput.setSelectionRange ) {
+                oInput.setSelectionRange(oStart,oEnd);
+             }
+             else if( oInput.createTextRange ) {
+                var range = oInput.createTextRange();
+                range.collapse(true);
+                range.moveEnd('character',oEnd);
+                range.moveStart('character',oStart);
+                range.select();
+             }
+       }
+
+        // FIXME: Use prototype instead of event handler per element
+        // dojo.widget.Button.prototype.onClick=function(){}
+        var updates = {}
+        var bindArgs = {
+                       url: "/jsonrpc",
+                       type: "text/javascript",
+                       load: function(type, data, evt){
+                                updates = eval(data)
+                                execUpdates()
+                             }
+        }
+
+function updateWidgets() {
+     list=dojo.widget.manager.getWidgetsByType("TextBox");
+     for (i in list) {
+        list[i].textbox.style.width=list[i].domNode.parentNode.style.width;
+        list[i].textbox.style.height=list[i].domNode.parentNode.style.height;
+        dojo.event.connect(list[i].textbox, "onchange", function(e){
+           sendCmd("onChange","id="+e.target.id+"&text="+e.target.value)
+        }
+        );
+     }
+}
+
+dojo.addOnLoad(updateWidgets);
+
+        function getUid() {
+           myURL = window.location.href
+           x=myURL.indexOf("/session_")
+           return myURL.substring(x+9,x+41)
+        }
+        function sendCmd(cmd, args) {
+          bindArgs.url="/jsonrpc_"+getUid()+"?cmd="+cmd+"&"+args
+          dojo.io.bind(bindArgs);
+        }
+
+        function execUpdates() {
+          for (i in updates) {
+            item=updates[i];
+            try  {
+              if (item[0]=="alert") {
+                 //alert(item[2])
+                 document.getElementById("basic_title").innerHTML=item[1];
+                 var msg=item[2];
+                 if (msg[0]!="<") { msg="<PRE>"+msg+"</PRE>" };
+                 document.getElementById("basic_content").innerHTML=msg;
+                 var btn=document.getElementById("basic_button");
+                 dlg=dojo.widget.getWidgetById("basicDialog")
+                 dlg.setCloseControl(btn);
+                 dlg.show()
+              }
+              if (item[0]=="status") {
+                 window.status=item[2]
+              }
+
+              if (item[0]=="set") {
+                 elem = dojo.widget.getWidgetById(item[1])
+                 if (elem==undefined) {
+                    elem = document.getElementById(item[1])
+                }
+                if (elem.textbox!=undefined) {
+                  elem.textbox.value=item[2];
+                } else {
+                elem.value=item[2];
+                }
+              }
+              if (item[0]=="replace") {
+                 elem = document.getElementById(item[1])
+                 elem.innerHTML=item[2]
+              }
+              if (item[0]=="disable") {  // disable id true/false
+                 elem = dojo.widget.getWidgetById(item[1])
+                 if (elem==undefined) {
+                    elem = document.getElementById(item[1])
+                    elem.disabled=item[2];
+                 } else {
+                    if (item[2]==true) {
+                      elem.disable()
+                    } else {
+                      elem.enable()
+                    }
+                 }
+               }
+               if (item[0]=="activate") {  // toggle id
+                 elem = dojo.widget.getWidgetById(item[1])
+                 if (!(elem==undefined)) {
+                    if (item[2]==true) {
+                      elem.select()
+                    } else {
+                      elem.deselect()
+                    }
+                 }
+               }
+               if (item[0]=="grab_focus") {
+                    elem = document.getElementById(item[1])
+                    if (elem==undefined) {
+                       elem = dojo.widget.getWidgetById(item[1])
+                       elem.focus()
+                    } else {
+                       elem.focus()
+                    }
+               }
+               if (item[0]=="set_page") {
+                    elem = dojo.widget.getWidgetById(item[2])
+
+               }
+               if (item[0]=="set_cursor") {
+                    elem = document.getElementById(item[1])
+                    if (elem==undefined) {
+                       elem = dojo.widget.getWidgetById(item[1])
+                    }
+                    setCursorPosition(elem,item[2],item[2])
+               }
+               if (item[0]=="select_region") {
+                    elem = document.getElementById(item[1])
+                    if (elem==undefined) {
+                       elem = dojo.widget.getWidgetById(item[1])
+                    }
+                    selection_start = item[2][0]
+                    selection_end = item[2][1]
+                    setCursorPosition(elem,selection_start,selection_end )
+               }
+               if (item[0]=="close") {
+                    // return to main page
+                    window.location="/"
+               }
+            }
+            catch(err)  {
+                   txt="There was an error on this page.\\n\\n"
+                   txt+="Id: " + item[1] + "\\n"
+                   txt+="Value: " + item[2] + "\\n"
+                   txt+="Error Name: " + err.name + "\\n"
+                   txt+="Error Message: " + err.message + "\\n\\n"
+                   txt+="Click OK to continue.\\n\\n"
+                   // err.fileName + err.lineNumber
+                   dojo.debug(txt)
+            }
+          }
+        }


Property changes on: trunk/gnue-forms/src/uidrivers/html/gnue.js
___________________________________________________________________
Name: svn:executable
   + *

Modified: trunk/gnue-forms/src/uidrivers/html/widgets/entry.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/widgets/entry.py        2007-03-27 
18:13:56 UTC (rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/widgets/entry.py        2007-03-28 
12:17:10 UTC (rev 9451)
@@ -39,7 +39,6 @@
         if object.style == 'dropdown' or \
           object.style == 'listbox':
             choices = []
-            # FIXME: choices get initialized in _ui_set_choices_()
 
             if object.style == "listbox":
                 dhtml=build_entry_listbox(id, "%s", choices, 
object.Char__height,
@@ -68,10 +67,16 @@
                                           self.itemY, self.itemWidth, \
                                           self.itemHeight)
 
-        else: # normal text box
+        else: # normal text box - just digits
+            textbox_style = "Textbox"
+            # Textbox", IntegerTextbox, DateTextbox, TimeTextbox
             dhtml = build_entry_default(id, "%s", 
object.Char__x*event.widgetWidth,\
-                                        self.itemY, self.itemWidth, 
self.itemHeight)
+                                        self.itemY, self.itemWidth, 
self.itemHeight, 
+                                        textbox_style)
+            # ["set_cursor", "141", 0], ["select_region", "141", [0, 0]]]
             
+            
+            
         newWidget = HtmlEntryWidget(event.container, self._uiDriver, 'ENTRY', 
dhtml, id)
         newWidget.style=object.style
 
@@ -92,7 +97,16 @@
     def _ui_disable_(self, index):
         self.widgets[index].set_sensitive(False)
 
+    # 
---------------------------------------------------------------------------
+    # Set "editable" status for this widget
+    # 
---------------------------------------------------------------------------
 
+    def _ui_set_editable_(self, index, editable):
+
+        # FIXME: grey out entry, disallow changes if possible
+        pass
+
+
     # 
---------------------------------------------------------------------------
     # Set the cursor position in a widget to position
     # 
---------------------------------------------------------------------------
@@ -106,7 +120,44 @@
 
         widget.set_cursor_pos(position)
 
+    # -------------------------------------------------------------------------
 
+    def _ui_copy_(self, index):
+
+        widget = self.widgets[index]
+
+        if hasattr(widget, 'copy_clipboard'):
+            widget.copy_clipboard()
+
+    # -------------------------------------------------------------------------
+
+    def _ui_paste_(self, index):
+
+        widget = self.widgets[index]
+
+        if hasattr(widget, 'paste_clipboard'):
+            widget.paste_clipboard()
+
+    # -------------------------------------------------------------------------
+
+    def _ui_select_all_(self, index):
+
+        widget = self.widgets[index]
+
+        if hasattr(widget, 'select_region'):
+            widget.set_position(-1)
+            pos = widget.get_position()
+            widget.select_region(0, -1)
+            bounds = widget.get_selection_bounds()
+            # There seems to be no event that is fired when the selection of an
+            # entry changes, so we must notify the GF layer ourselves.
+            # FIXME: This also means that selecting "Select All" from the
+            # context menu of the entry doesn't work.
+            self._request('SELECTWITHMOUSE', position1=bounds[0],
+                    position2=bounds[1], cursor=pos)
+
+
+
     # 
---------------------------------------------------------------------------
     # set the selected area
     # 
---------------------------------------------------------------------------

Modified: trunk/gnue-forms/src/uidrivers/html/widgets/form.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/html/widgets/form.py 2007-03-27 18:13:56 UTC 
(rev 9450)
+++ trunk/gnue-forms/src/uidrivers/html/widgets/form.py 2007-03-28 12:17:10 UTC 
(rev 9451)
@@ -61,7 +61,7 @@
             # FIXME: add dialogs
         else:
             newWidget = HtmlWidget(event.container, self._uiDriver, 'FORM', 
dhtml, getNextId())
-            
+
         self.mainWindow = newWidget
         self.mainWindow.updates = []
 
@@ -149,7 +149,7 @@
     def _ui_update_status_ (self, tip, record_status, insert_status,
             record_number, record_count, page_number, page_count):
 
-        # create and update status bar
+        # TODO:  create and update status bar
         pass
 
 
@@ -170,11 +170,18 @@
         @return: True if the Ok-, Close-, or Yes-button was pressed, False if 
the
             No-button was pressed or None if the Cancel-button was pressed.
         """
-        # FIXME: Display dialog box
-        self.mainWindow.updates.append(["alert","",message])
-        return False
 
+        result=True
+        if cancel or kind=="Question":
+            id=23242
+            self.mainWindow.updates.append(["message",id,[message,kind, title, 
cancel]])
+            result=self.mainWindow.controller.waitResult(id)
+        else:
+            self.mainWindow.updates.append(["alert",title,message])
 
+        return result
+
+
     # 
---------------------------------------------------------------------------
     # Display an about box
     # 
---------------------------------------------------------------------------
@@ -186,7 +193,7 @@
     Author: %s
     Description: %s
         """) % (name, version, author, description)
-        self.mainWindow.updates.append(["alert","",message])
+        self.mainWindow.updates.append(["alert","About",message])
 
     # 
---------------------------------------------------------------------------
     # Print form screenshot
@@ -194,7 +201,7 @@
 
     def _ui_printout_(self, title, subtitle, user):
         message = u_("Printout currently not supported")
-        self.mainWindow.updates.append(["alert","",message])
+        self.mainWindow.updates.append(["alert","Info",message])
 
 
     # 
---------------------------------------------------------------------------





reply via email to

[Prev in Thread] Current Thread [Next in Thread]