├── MANIFEST.in
├── screenshot
├── demo1.png
├── demo2.png
├── demo3.png
├── findgui.png
└── SimpleDemo.png
├── FormUI
├── __init__.py
├── BuilderUtil.py
├── WorkThread.py
├── FormUI.py
├── FormControlBase.py
├── ControlBase.py
├── Frame.py
├── Builder.py
├── FormControl.py
└── Form.py
├── .idea
├── vcs.xml
├── encodings.xml
├── misc.xml
├── inspectionProfiles
│ └── profiles_settings.xml
├── modules.xml
└── pyFormUI.iml
├── Demo
├── customcontrol.xml
├── demo_menu.xml
├── SimpleDemo.xml
├── SimpleDemo.py
├── demo_common.xml
├── demo_others.xml
├── findgui.xml
├── CustomControl.py
├── demo.xml
├── FindGui.py
└── Demo.py
├── setup.py
├── LICENSE
└── Readme.md
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include Demo/*.xml
2 |
--------------------------------------------------------------------------------
/screenshot/demo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffchau1979/pyFormUI/HEAD/screenshot/demo1.png
--------------------------------------------------------------------------------
/screenshot/demo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffchau1979/pyFormUI/HEAD/screenshot/demo2.png
--------------------------------------------------------------------------------
/screenshot/demo3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffchau1979/pyFormUI/HEAD/screenshot/demo3.png
--------------------------------------------------------------------------------
/screenshot/findgui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffchau1979/pyFormUI/HEAD/screenshot/findgui.png
--------------------------------------------------------------------------------
/screenshot/SimpleDemo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffchau1979/pyFormUI/HEAD/screenshot/SimpleDemo.png
--------------------------------------------------------------------------------
/FormUI/__init__.py:
--------------------------------------------------------------------------------
1 | from Builder import Builder
2 | from Form import WindowHandler
3 | from FormUI import FormUI
4 | from FormControlBase import *
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Demo/customcontrol.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Demo/demo_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/SimpleDemo.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.idea/pyFormUI.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | from setuptools import setup, find_packages
5 |
6 | setup(
7 | name = 'pyFormUI',
8 | version = '0.1',
9 | description = 'A Simple Form GUI for python',
10 | author = 'zhangfeng.zou',
11 | author_email = 'jeff.chau@hotmail.com',
12 | url = 'https://www.en7788.com',
13 | license="MIT",
14 | keywords = 'GUI wxpython Form',
15 | package_dir = {
16 | 'FormUI' : 'FormUI',
17 | 'Demo' : 'Demo',
18 | '':'.'
19 | },
20 | packages=["Demo", "FormUI"],
21 | include_package_data=True,
22 | package_data = {
23 | 'Demo':['Demo/*.xml'],
24 | },
25 | install_requires=['wxpython'],
26 | )
27 |
--------------------------------------------------------------------------------
/Demo/SimpleDemo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 | import sys
12 | sys.path.append('../')
13 |
14 | from FormUI import *
15 |
16 | #Load layout xml file
17 | builder = Builder()
18 | builder.loadLayout('SimpleDemo.xml')
19 |
20 | #Setup Handler
21 | def OkButtonHandler(windowHandler, handlerPara):
22 | print handlerPara.getValue('id_text')
23 | windowHandler.closeWindow()
24 | builder.setCtrlHandler('id_ok', OkButtonHandler)
25 |
26 | #Show FormUI
27 | formUI = FormUI(builder)
28 | formUI.show()
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 jeffchau1979
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/FormUI/BuilderUtil.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 | #from CommonCtrl import *
12 |
13 | #Some static methods for Builder
14 | class BuilderUtil():
15 | def __init__(self):
16 | pass
17 |
18 | @staticmethod
19 | def convertStyle(style):
20 | ret = {}
21 | itemList = style.split(';')
22 | for item in itemList:
23 | keyValue = item.split(':')
24 | if len(keyValue) > 1:
25 | ret[keyValue[0]] = keyValue[1]
26 | return ret
27 |
28 | @staticmethod
29 | def convertBool(item):
30 | if isinstance(item, bool):
31 | return item
32 | return str(item).lower() == 'true'
33 |
34 | @staticmethod
35 | def getItemValue(item, key, defaultValue=""):
36 | if key in item.keys():
37 | return item[key]
38 | else:
39 | return defaultValue
--------------------------------------------------------------------------------
/Demo/demo_common.xml:
--------------------------------------------------------------------------------
1 |
2 |
37 |
--------------------------------------------------------------------------------
/Demo/demo_others.xml:
--------------------------------------------------------------------------------
1 |
2 |
46 |
--------------------------------------------------------------------------------
/Demo/findgui.xml:
--------------------------------------------------------------------------------
1 |
2 |
63 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | ========================================
2 | pyFormUI -- A Simple Form GUI for python
3 | ========================================
4 | pyFormUI provide the most easy way to show a Form Dialog for python,which is based on the cross-platform library wxPython.pyFormUI use xml file to design GUI, no any wxpython Knowledge is need when using pyFormUI.
5 |
6 |
7 |
8 |
9 |
10 | Installation
11 | ------------
12 | #### 1.install wxpython
13 | ```bash
14 | sudo apt-get install python-wxtools
15 | ```
16 | #### 2.Download pyFormUI Source and Install pyFormUI from source:
17 | ```bash
18 | cd pyFormUI_Source_Folder
19 | python setup.py install
20 | ```
21 |
22 | Simple Example:
23 | ------------
24 | Please Find the code of this Example in files Demo/SimpleDemo.py and Demo/SimpleDemo.xml
25 |
26 |
27 |
28 | #### 1.Create GUI by xml
29 | ```xml
30 |
31 |
40 | ```
41 | #### 2.Show GUI by xml layout
42 | ```python
43 | from FormUI import *
44 | builder = Builder()
45 | builder.loadLayout('demo.xml')
46 | formUI = FormUI(builder)
47 | formUI.show()
48 | ```
49 |
50 | #### 3.Add handler for button or other controls
51 | ```python
52 | def OkButtonHandler(windowHandler, handlerPara):
53 | print handlerPara.getValue('id_text')
54 | windowHandler.closeWindow()
55 | builder.setCtrlHandler('id_ok', OkButtonHandler)
56 | ```
57 |
58 | More Demos
59 | ------------
60 | Find more Demos in Demo Folder.
61 |
62 | #### 1.Demo.py
63 | ```bash
64 | python Demo.py
65 | ```
66 |
67 | this demo show the basic control of pyFormUI
68 |
69 | #### 2.FindGui.py
70 | ```bash
71 | python FindGui.py
72 | ```
73 |
74 | This Demo Implement the GUI for linux find cmd.
75 |
76 |
77 |
78 |
79 | #### 3.SimpleDemo.py
80 | ```bash
81 | python SimpleDemo.py
82 | ```
83 |
84 | A Simple Demo
85 |
86 | #### 4.CustomControl.py
87 | ```bash
88 | python CustomControl.py
89 | ```
90 |
91 | A Demo Show how to add cutom control
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Demo/CustomControl.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 | import sys
12 | sys.path.append('../')
13 |
14 | from FormUI import *
15 |
16 | #Load layout xml file
17 | builder = Builder()
18 | builder.loadLayout('customcontrol.xml')
19 |
20 | #Setup Handler
21 | def OkButtonHandler(windowHandler, handlerPara):
22 | print handlerPara.valueList
23 | windowHandler.highlightItem('id_custom_ctrl')
24 | windowHandler.enableCtrl('id_custom_ctrl',False)
25 | print windowHandler.sendMessage('id_custom_ctrl', 'get_message', '')
26 | windowHandler.sendMessage('id_custom_ctrl', 'set_message', 'message_para')
27 | #windowHandler.closeWindow()
28 | builder.setCtrlHandler('id_ok', OkButtonHandler)
29 |
30 |
31 | class CustomCtrl(FormControlBase,wx.BoxSizer):
32 | def __init__(self, item, parent, windowControl):
33 | wx.BoxSizer.__init__(self, wx.HORIZONTAL)
34 | FormControlBase.__init__(self, item, parent)
35 |
36 | self.staticText = wx.StaticText(id=wx.NewId(),
37 | label='Label:', name='', parent=parent,
38 | pos=wx.Point(0, 0), size=wx.Size(-1, -1),
39 | style=0)
40 | self.Add(self.staticText, 0, wx.ALL)
41 | para = FormControlUtil.makeCommonPara(item,parent)
42 | if 'multi_line' in item.keys() and getItemValue(item, 'multi_line') == 'true':
43 | para['style'] = para['style'] | wx.TE_MULTILINE
44 | if 'password' in item.keys() and getItemValue(item, 'password') == 'true':
45 | para['style'] = para['style'] | wx.TE_PASSWORD
46 | para['value'] = BuilderUtil.getItemValue(item, 'value', '')
47 | self.m_textCtrl = wx.TextCtrl(**para)
48 | self.Add(self.m_textCtrl, 1, wx.ALL | wx.EXPAND)
49 |
50 | def GetValue(self):
51 | return self.m_textCtrl.GetValue()
52 |
53 | def SetValue(self,value):
54 | self.m_textCtrl.SetValue(value)
55 | def Enable(self,bEnable):
56 | self.m_textCtrl.Enable(bEnable)
57 | def SetFocus(self):
58 | self.m_textCtrl.SetFocus()
59 | def onMessage(self, messageId, messagePara):
60 | if messageId == 'get_message':
61 | return "message:" + self.item['control'].GetValue()
62 | elif messageId == "set_message":
63 | self.item['control'].SetValue(messageId + ":" + messagePara)
64 | return None
65 | builder.registControlType('custom_ctrl', CustomCtrl)
66 |
67 | #Show FormUI
68 | formUI = FormUI(builder)
69 | formUI.show()
70 |
--------------------------------------------------------------------------------
/FormUI/WorkThread.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | from Form import *
13 | import threading
14 | from Queue import *
15 | import traceback
16 |
17 | EVENT_TYPE_APP_CLOSE = 1
18 | EVENT_TYPE_WINDOW_CONTROL = 2
19 | EVENT_TYPE_SUB_FORM_CLOSE = 3
20 |
21 | EVENT_WORKTHREAD_UPDATE = 1
22 | EVENT_WORKTHREAD_CLOSE = 2
23 | EVENT_WORKTHREAD_SHOW = 3
24 | EVENT_WORKTHREAD_SHOW_ITEM = 4
25 | EVENT_WORKTHREAD_ENABLE_ITEM = 5
26 | EVENT_WORKTHREAD_HIGHLIGHT_ITEM = 6
27 | EVENT_WORKTHREAD_MESSAGEBOX = 7
28 | EVENT_WORKTHREAD_CONFIRM_MESSAGEBOX = 8
29 | EVENT_UITHREAD_HANDLER_FINISH = 9
30 | EVENT_WORKTHREAD_ENABLE_MENU = 10
31 | EVENT_WORKTHREAD_ITEM_SET_VALUE = 11
32 | EVENT_WORKTHREAD_SHOWFORM = 12
33 | EVENT_WORKTHREAD_MESSAGE = 13
34 |
35 | #The Work Thread Runnable
36 | def workThreadRunnable(workQueue):
37 | thread_stop = False
38 | returnState = False
39 | valueList= {}
40 | while not thread_stop:
41 | try:
42 | task = workQueue.get(block=True)
43 | except Queue.Empty:
44 | thread_stop = True
45 | break
46 | eventType = task[0]
47 | windowHandler = task[1]
48 | para = task[2]
49 | if eventType == EVENT_TYPE_WINDOW_CONTROL:
50 | try:
51 | para.handler(windowHandler,para)
52 | except Exception,ex:
53 | traceback.print_exc()
54 | windowHandler.showWindow(False)
55 | raw_input("Press Enter Key to continue:")
56 | windowHandler.showWindow(True)
57 | #windowHandler.taskDone()
58 |
59 | if not windowHandler.window or windowHandler.window.windowState == windowHandler.window.WINDOW_STATE_CLOSED:
60 | returnState = windowHandler.returnOk
61 | valueList = para.valueList
62 | elif eventType == EVENT_TYPE_APP_CLOSE:
63 | break
64 | else:
65 | continue
66 |
67 | workQueue.task_done()
68 | return returnState, valueList
69 |
70 | #The work Thread for Form shown by handler
71 | class SubFormThread(threading.Thread):
72 | def __init__(self, waitQueue):
73 | threading.Thread.__init__(self)
74 | self.queue = Queue(30)
75 | self.returnState = False
76 | self.valueList = {}
77 | self.waitQueue = waitQueue
78 | def run(self):
79 | self.returnState, self.valueList = workThreadRunnable(self.queue)
80 | self.waitQueue.put([EVENT_TYPE_SUB_FORM_CLOSE, None, None], block=True, timeout=None)
81 |
--------------------------------------------------------------------------------
/FormUI/FormUI.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | ################################
13 | #FormUI is runing on UIThread instead of main thread, in case which can cowork with other application.
14 | #Another advantage is main thread can launch other gui application.
15 | ###############################
16 |
17 | from Form import *
18 | from WorkThread import *
19 | import Frame
20 | import threading
21 | import Queue
22 | import json
23 | import uuid
24 | modules ={u'Frame': [1, 'Main frame of Application', u'Frame.py']}
25 |
26 | import warnings
27 | warnings.filterwarnings("ignore",".*trying to remove*")
28 |
29 | ##The Application
30 | class FormDialogApp(wx.App):
31 | def __init__(self, parent, builder, workQueue):
32 | super(FormDialogApp, self).__init__(parent)
33 | self.main = Frame.create(None, builder, workQueue)
34 | if self.main.initSuccess:
35 | self.main.Show()
36 | self.SetTopWindow(self.main)
37 |
38 | #The UI Thread
39 | #not the main Thread
40 | class UIThread(threading.Thread):
41 | def __init__(self, builder,workQueue):
42 | threading.Thread.__init__(self)
43 | self.workQueue = workQueue
44 | self.application = FormDialogApp(0, builder, workQueue)
45 | def run(self):
46 | self.application.MainLoop()
47 |
48 | ##FormUI
49 | ##Used to build Form UI Application
50 | class FormUI():
51 | def __init__(self, builder):
52 | self.builder = builder
53 | self.returnState = False
54 |
55 | def show(self):
56 | queue = Queue.Queue(30)
57 | uiThread = UIThread(self.builder, queue)
58 | uiThread.start()
59 | self.returnState, self.valueList = workThreadRunnable(queue)
60 |
61 | @staticmethod
62 | def getUUIDString():
63 | return "%s" % uuid.uuid1()
64 |
65 | @staticmethod
66 | def loadCachedValue(cachedValueFile):
67 | cachedValue = {}
68 | try:
69 | fileHandle = open(cachedValueFile)
70 | jsonContent = fileHandle.read()
71 | fileHandle.close()
72 | cachedValue = json.loads(jsonContent)
73 | except IOError as err:
74 | print "read value configure file fail!"
75 | return cachedValue
76 |
77 | def saveCachedValue(self, cachedValueFile, valueList = None):
78 | if valueList is None and self.returnState:
79 | valueList = self.valueList
80 | if valueList is None:
81 | return
82 | try:
83 | jsonContent = json.dumps(valueList)
84 | fileHandle = open(cachedValueFile, 'w')
85 | fileHandle.write(jsonContent)
86 | fileHandle.close()
87 | except IOError as err:
88 | print "write value configure file fail"
89 |
90 |
--------------------------------------------------------------------------------
/Demo/demo.xml:
--------------------------------------------------------------------------------
1 |
2 |
89 |
--------------------------------------------------------------------------------
/Demo/FindGui.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 | import sys
12 | sys.path.append('../')
13 |
14 | import wx
15 | from FormUI import *
16 | import subprocess
17 | import os
18 | import sys
19 |
20 | builder = Builder()
21 |
22 | #laod Layout
23 | builder.loadLayout(os.path.split(os.path.realpath(__file__))[0] + os.path.sep + 'findgui.xml')
24 |
25 | #setup Handler
26 | def OkButtonHandler(windowHandler, handlerPara):
27 | cmd = ""
28 | id_search = handlerPara.getValue('id_search')
29 | if handlerPara.getValue('id_search_type') == "Default":
30 | cmd = cmd + " -name "
31 | elif handlerPara.getValue('id_search_type') == "Ignore Case":
32 | cmd = cmd + " -iname "
33 | elif handlerPara.getValue('id_search_type') == "Full Path":
34 | cmd = cmd + " -path "
35 | if not '*' in handlerPara.getValue('id_search'):
36 | id_search = "*" + handlerPara.getValue('id_search') + '*'
37 | cmd = cmd + "'" + id_search + "'"
38 |
39 | if handlerPara.getValue('id_size_large') != "":
40 | cmd = cmd + " -size +" + handlerPara.getValue('id_size_large') + handlerPara.getValue('id_size_large_unit')
41 | if handlerPara.getValue('id_size_small') != "":
42 | cmd = cmd + " -size -" + handlerPara.getValue('id_size_small') + handlerPara.getValue('id_size_small_unit')
43 |
44 | if handlerPara.getValue('id_modify_after') != "":
45 | if handlerPara.getValue('id_modify_after_unit') == 'day':
46 | cmd = cmd + " -mtime +" + handlerPara.getValue('id_modify_after')
47 | elif handlerPara.getValue('id_modify_after_unit') == 'min':
48 | cmd = cmd + " -mmin +" + handlerPara.getValue('id_modify_after')
49 |
50 | if handlerPara.getValue('id_access_after') != "":
51 | if handlerPara.getValue('id_access_after_unit') == 'day':
52 | cmd = cmd + " -mtime +" + handlerPara.getValue('id_access_after')
53 | elif handlerPara.getValue('id_access_after_unit') == 'min':
54 | cmd = cmd + " -mmin +" + handlerPara.getValue('id_access_after')
55 |
56 | if handlerPara.getValue('id_type') != "any":
57 | valueMap = {}
58 | valueMap['file'] = 'f'
59 | valueMap['directory'] = 'd'
60 |
61 | cmd = cmd + " -type " + valueMap[handlerPara.getValue('id_type')]
62 |
63 | if handlerPara.getValue('id_excute') != "":
64 | cmd = cmd + " -exec "+handlerPara.getValue('id_excute')+" {} \;"
65 |
66 | if handlerPara.getValue('id_search_text') != "":
67 | cmd = cmd + " |xargs grep " + handlerPara.getValue('id_search_text')
68 |
69 | if handlerPara.getValue('id_save_file') != "":
70 | cmd = cmd + " > " + handlerPara.getValue('id_save_file')
71 |
72 | windowHandler.closeWindow()
73 | paths = handlerPara.getValue('id_path')
74 | paths = paths.split('\n')
75 | for path in paths:
76 | if path != '':
77 | print('\033[1;31;40m' + "Path:" + path + '\033[0m')
78 | gCmdLine ="find " + path + " " + cmd
79 | print(gCmdLine)
80 | subprocess.call([gCmdLine], shell=True)
81 | builder.setCtrlHandler('id_btn_search', OkButtonHandler)
82 |
83 | def GuiFind():
84 | valueList = FormUI.loadCachedValue(os.path.expanduser('~') + ".findgui.cfg")
85 | builder.updateValue(valueList)
86 | #builder.setValue('id_search_text','')
87 | formUI = FormUI(builder)
88 | formUI.show()
89 | formUI.saveCachedValue(os.path.expanduser('~') + ".findgui.cfg")
90 | #return gCmdLine
91 | GuiFind()
--------------------------------------------------------------------------------
/FormUI/FormControlBase.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | from ControlBase import *
13 |
14 | import wx.lib.filebrowsebutton
15 |
16 | #From Control Util,
17 | #Some static method for Form Control
18 | class FormControlUtil():
19 | @staticmethod
20 | def makeCommonPara(item,parent):
21 | itemWidth = -1
22 | if 'width' in item.keys():
23 | itemWidth = int(item['width'])
24 | itemHeight = -1
25 | if 'height' in item.keys():
26 | itemHeight = int(item['height'])
27 | align = FormControlUtil.getAlign(item)
28 |
29 | para ={}
30 | para['size'] = wx.Size(itemWidth, itemHeight)
31 | para['pos'] = wx.Point(0, 0)
32 | para['name'] = BuilderUtil.getItemValue(item, 'id')
33 | para['parent'] = parent
34 | para['id'] = wx.NewId()
35 | item['event_id'] = para['id']
36 | para['style'] = align
37 | return para
38 |
39 | @staticmethod
40 | def getLable(item):
41 | if 'label' in item.keys():
42 | labelText = BuilderUtil.getItemValue(item, 'lable', "")
43 | elif 'title' in item.keys():
44 | labelText = BuilderUtil.getItemValue(item, 'title', "")
45 | else:
46 | return ''
47 |
48 | if '\\t' in labelText:
49 | labelText = labelText[:labelText.find('\\t')]
50 | return labelText
51 |
52 | @staticmethod
53 | def getAccelerator(item):
54 | if 'label' in item.keys():
55 | labelText = BuilderUtil.getItemValue(item, 'lable', "")
56 | elif 'title' in item.keys():
57 | labelText = BuilderUtil.getItemValue(item, 'title', "")
58 | else:
59 | return None
60 |
61 | if '\\t' in labelText:
62 | labelText = labelText[labelText.find('\\t')+2:]
63 | return labelText
64 | else:
65 | return None
66 |
67 | @staticmethod
68 | def convertList(item):
69 | if isinstance(item, list):
70 | return item
71 | retList = []
72 | if item is None:
73 | return retList
74 | strList = item.split(';')
75 | for str in strList:
76 | str = str.replace('[semicolon]', ';')
77 | str = str.replace('[bar]', '|')
78 | str = str.replace('[bracketleft]', '[')
79 | str = str.replace('[bracketright]', ']')
80 | retList.append(str)
81 | return retList
82 | @staticmethod
83 | def conventBool(item):
84 | if isinstance(item,bool):
85 | return item
86 | return str(item).lower() == 'true'
87 |
88 | @staticmethod
89 | def getAlign(item):
90 | if 'align' in item.keys():
91 | align = BuilderUtil.getItemValue(item,'align','left')
92 | alignText = str(align)
93 | if alignText == 'center':
94 | return wx.ALIGN_CENTER
95 | elif alignText == 'right':
96 | return wx.ALIGN_RIGHT
97 | elif alignText == 'left' :
98 | return wx.ALIGN_LEFT
99 | else:
100 | return align
101 | return 0
102 |
103 | #Form Control Base Class
104 | class FormControlBase():
105 | def __init__(self,item,parent):
106 | self.item = item
107 | item['control'] = self
108 | self.parent = parent
109 | def onMessage(self,messageId, messagePara):
110 | return None
111 |
--------------------------------------------------------------------------------
/Demo/Demo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | import sys
13 | sys.path.append('../')
14 |
15 | from FormUI import *
16 | import os
17 |
18 | builder = Builder()
19 |
20 | #laod Layout
21 |
22 | #builder.loadLayout('demo_menu.xml')
23 | #builder.mergeLayout('demo_common.xml')
24 | #builder.mergeLayout('demo_others.xml')
25 | builder.loadLayout('demo.xml')
26 |
27 | #Setup Handler
28 | def OkButtonHandler(windowHandler, handlerPara):
29 | print(handlerPara.getEventId() + ":" + handlerPara.getEventType())
30 | valueList = handlerPara.valueList
31 | for k, v in valueList.iteritems():
32 | print "result[%s]=" % k, v
33 | windowHandler.update(builder,True)
34 | windowHandler.closeWindow()
35 | builder.setCtrlHandler('id_ok', OkButtonHandler)
36 |
37 | def cancelButtonHandler(windowHandler, handlerPara):
38 | windowHandler.closeWindow()
39 | builder.setCtrlHandler('id_cancel', cancelButtonHandler)
40 |
41 |
42 | def button_handler(windowHandler, handlerPara):
43 | #windowHandler.setValue('id_text', 'button onclick')
44 | #ret = windowHandler.confirmMessageBox("ok button click", "title")
45 | #windowHandler.enableCtrl('id_multi_files', False)
46 | #windowHandler.highlightItem('id_multi_files')
47 | #builder.setCtrlAttribute('id_text','width',100)
48 | builder.setCtrlAttribute('id_text', 'value', 'update builder')
49 | windowHandler.update(builder,True)
50 | builder.setCtrlHandler('id_button', button_handler)
51 |
52 | builderFind = Builder()
53 | builderFind.loadLayout('findgui.xml')
54 | def findOk(windowHandler, handlerPara):
55 | windowHandler.closeWindow()
56 | builderFind.setCtrlHandler('id_btn_search', findOk)
57 |
58 | def button_findgui_handler(windowHandler, handlerPara):
59 | state, valueList = windowHandler.showForm(builderFind,True)
60 | print valueList
61 | builder.setCtrlHandler('id_button_findgui', button_findgui_handler)
62 |
63 | def menu_handler(windowHandler, handlerPara):
64 | windowHandler.closeWindow()
65 | builder.setCtrlHandler('id_menu', menu_handler)
66 |
67 | def onlist(windowHandler, handlerPara):
68 | print(handlerPara.getEventType()+":" +handlerPara.getValue('id_list'))
69 | builder.setCtrlHandler('id_list', onlist)
70 |
71 | tableData = []
72 | def AddTableLine(tableData, id, items):
73 | line = {}
74 | line['id'] = id
75 | line['items'] = items
76 | tableData.append(line)
77 | AddTableLine(tableData,'1',"apple;1;red")
78 | AddTableLine(tableData,'2',"orange;2;yellow")
79 | AddTableLine(tableData,'3',"lemon;3;yellow")
80 | AddTableLine(tableData,'4',"peach;4;pink")
81 | builder.setCtrlAttribute('id_table','data', tableData)
82 |
83 | def AddTreeNode(parent,id,title):
84 | node = {}
85 | node['id'] = id
86 | node['title'] = title
87 | node['subNodes'] = []
88 | if parent is not None:
89 | parent['subNodes'].append(node)
90 | return node
91 |
92 | treeData = AddTreeNode(None,'id_node','Node')
93 | node1 = AddTreeNode(treeData, 'id_node1', 'Node1')
94 | node2 = AddTreeNode(node1, 'id_node2', 'Node2')
95 | node21 = AddTreeNode(node1, 'id_node21', 'Node21')
96 | node22 = AddTreeNode(node1, 'id_node22', 'Node22')
97 | node3 = AddTreeNode(node1, 'id_node3', 'Node3')
98 | node4 = AddTreeNode(node3, 'id_node4', 'Node4')
99 | node41 = AddTreeNode(node3, 'id_node41', 'Node41')
100 | node42 = AddTreeNode(node3, 'id_node42', 'Node42')
101 | builder.setCtrlAttribute('id_tree','data', treeData)
102 |
103 | #Show FormUI
104 | valueList = FormUI.loadCachedValue(os.path.expanduser('~') + "/.demo.cfg")
105 | builder.updateValue(valueList)
106 | formUI = FormUI(builder)
107 | formUI.show()
108 | formUI.saveCachedValue(os.path.expanduser('~') + "/.demo.cfg")
109 |
--------------------------------------------------------------------------------
/FormUI/ControlBase.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 | import wx
12 | import wx.lib.masked.timectrl
13 | import wx.lib.filebrowsebutton
14 | from Builder import *
15 | import os
16 |
17 |
18 | def EnableSizer(item, bEnable):
19 | children = item.GetChildren()
20 | for child in children:
21 | widget = child.GetWindow()
22 | if widget is not None:
23 | widget.Enable(bEnable)
24 | elif isinstance(child, wx.SizerItem):
25 | EnableSizer(child.GetSizer(), bEnable)
26 |
27 | class DateTimeBase(wx.BoxSizer):
28 | ITEM_BORDER_WIDTH = 0
29 | def __init__(self,parent, pos, size,style=0,name='',id=''):
30 | wx.BoxSizer.__init__(self,wx.HORIZONTAL)
31 | self.m_datePicker = wx.DatePickerCtrl(parent, wx.NewId(), wx.DefaultDateTime,
32 | pos, wx.Size(0, size.height),
33 | wx.DP_DEFAULT)
34 | self.Add(self.m_datePicker, 1, wx.ALL|wx.EXPAND, self.ITEM_BORDER_WIDTH)
35 |
36 | self.m_time = wx.lib.masked.timectrl.TimeCtrl(display_seconds=True,
37 | fmt24hr=True, id=wx.NewId(),
38 | oob_color=wx.NamedColour('Yellow'), parent=parent,
39 | pos=pos,
40 | size=wx.Size(0, size.height),
41 | style=0, useFixedWidthFont=True)
42 | self.Add(self.m_time, 1, wx.ALL|wx.EXPAND, self.ITEM_BORDER_WIDTH)
43 | def GetValue(self):
44 | return self.m_datePicker.GetValue().FormatISODate() + " " + self.m_time.GetValue()
45 | def SetValue(self, value):
46 | valueList = value.split(" ")
47 | if len(valueList) > 1:
48 | dt = wx.DateTime()
49 | dt.ParseDate(valueList[0])
50 | self.m_datePicker.SetValue(dt)
51 |
52 | self.m_time.SetValue(valueList[1])
53 | def Enable(self, bEnable):
54 | EnableSizer(self, bEnable)
55 | def Show(self, bShow):
56 | self.ShowItems(bShow)
57 | def SetFocus(self):
58 | self.m_datePicker.SetFocus()
59 |
60 | class MultiFolderFileBase(wx.BoxSizer):
61 | ITEM_BORDER_WIDTH = 0
62 | ITEM_BORDER_BUTTON_SPACE = 1
63 | def __init__(self,parent, pos, size,mask,bAddFile,bAddFolder,style=0,name='',id=''):
64 | self.parent = parent
65 | self.mask = mask
66 | self.addFile = bAddFile
67 | self.addFolder = bAddFolder
68 | wx.BoxSizer.__init__(self,wx.HORIZONTAL)
69 |
70 | self.m_textCtrl = wx.TextCtrl(parent, wx.ID_ANY, wx.EmptyString, pos,
71 | wx.Size(0, size.height), wx.TE_MULTILINE|wx.HSCROLL)
72 | self.Add(self.m_textCtrl, 1, wx.ALL|wx.EXPAND, self.ITEM_BORDER_WIDTH)
73 |
74 | self.selectButtonSizer = self.createSelectButtons(pos)
75 | self.Add(self.selectButtonSizer, 0, wx.ALL, self.ITEM_BORDER_WIDTH)
76 | def createSelectButtons(self,pos):
77 | selectButtonSizer = wx.BoxSizer(orient=wx.VERTICAL)
78 | if self.addFile:
79 | selectFildId = wx.NewId()
80 | self.m_buttonSelectFile = wx.Button(self.parent, selectFildId, "Add File",
81 | pos,
82 | wx.Size(Builder.DEFAULT_BUTTON_WIDTH - self.ITEM_BORDER_WIDTH * 2 -self.ITEM_BORDER_BUTTON_SPACE,
83 | Builder.DEFAULT_LINE_HEIGHT), 0)
84 | selectButtonSizer.Add(self.m_buttonSelectFile, 0, wx.ALL, self.ITEM_BORDER_BUTTON_SPACE)
85 | self.m_buttonSelectFile.Bind(wx.EVT_BUTTON, self.OnButtonSelectFile, id=selectFildId)
86 | if self.addFolder:
87 | selectFolderId = wx.NewId()
88 | self.m_buttonSelectFolder = wx.Button(self.parent, selectFolderId, "Add Folder",
89 | pos,
90 | wx.Size(Builder.DEFAULT_BUTTON_WIDTH - self.ITEM_BORDER_WIDTH * 2 - self.ITEM_BORDER_BUTTON_SPACE,
91 | Builder.DEFAULT_LINE_HEIGHT), 0)
92 | selectButtonSizer.Add(self.m_buttonSelectFolder, 0, wx.ALL, self.ITEM_BORDER_BUTTON_SPACE)
93 | self.m_buttonSelectFolder.Bind(wx.EVT_BUTTON, self.OnButtonSelectFolder, id=selectFolderId)
94 | return selectButtonSizer
95 | def GetValue(self):
96 | return self.m_textCtrl.GetValue()
97 | def SetValue(self, value):
98 | self.m_textCtrl.SetValue(value)
99 |
100 | def OnButtonSelectFile(self, event):
101 | fileList = self.m_textCtrl.GetValue()
102 | fileList = fileList.split("\n")
103 | defaultFile = ''
104 | if len(fileList) > 0:
105 | defaultFile = fileList[-1]
106 | dirname, basename = os.path.split(defaultFile)
107 | dlg = wx.FileDialog(self.parent, message="Select Files",
108 | defaultDir=dirname,
109 | defaultFile=basename,
110 | wildcard=self.mask,
111 | style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
112 | if dlg.ShowModal() == wx.ID_OK:
113 | paths = dlg.GetPaths()
114 | for path in paths:
115 | if not path in fileList:
116 | fileList.append(path)
117 | self.SetValue("\n".join(fileList))
118 |
119 | def getPath(self,path):
120 | if os.path.isdir(path):
121 | return path
122 | elif os.path.isfile(path):
123 | return os.path.dirname(path)
124 | def OnButtonSelectFolder(self, event):
125 | fileList = self.m_textCtrl.GetValue()
126 | fileList = fileList.split("\n")
127 | defaultFile = ''
128 | if len(fileList) > 0:
129 | defaultFile = fileList[-1]
130 | dlg = wx.DirDialog(self.parent, "Select Folder", style=wx.DD_DEFAULT_STYLE)
131 | if defaultFile != '' and os.path.exists(defaultFile):
132 | dlg.SetPath(self.getPath(defaultFile))
133 | if dlg.ShowModal() == wx.ID_OK:
134 | path = dlg.GetPath()
135 | if not path in fileList:
136 | fileList.append(path)
137 | self.SetValue("\n".join(fileList))
138 | def Enable(self, bEnable):
139 | EnableSizer(self, bEnable)
140 | def Show(self, bShow):
141 | self.ShowItems(bShow)
142 | #ShowSizer(self, bShow)
143 | #ShowSizer(self.selectButtonSizer, bShow)
144 | def SetFocus(self):
145 | self.m_textCtrl.SetFocus()
146 |
147 | class StaticLineBase(wx.BoxSizer):
148 | STATIC_LINE_TEXT_EDGE = 20
149 | ITEM_BORDER_WIDTH = 0
150 | def __init__(self,parent, pos, size, label, style = wx.ALIGN_LEFT,name='',id=''):
151 | self.parent = parent
152 | wx.BoxSizer.__init__(self,wx.HORIZONTAL)
153 |
154 | if label == "":
155 | self.leftLine = wx.StaticLine(parent, wx.NewId(), wx.Point(0, 0), size,
156 | wx.LI_HORIZONTAL)
157 | self.Add(self.leftLine, 0, wx.ALL, 0)
158 | else:
159 | self.staticText = wx.StaticText(id=wx.NewId(),
160 | label=label, name='', parent=parent,
161 | pos=wx.Point(0, 0), size=wx.Size(-1, -1),
162 | style=0)
163 | textSize = self.staticText.GetSize()
164 | leftLineWidth = 0
165 | rightLineWidth = 0
166 | leftProportion = 1
167 | rightProportion = 1
168 | if style & wx.ALIGN_CENTER != 0:
169 | pass
170 | elif style & wx.ALIGN_RIGHT != 0:
171 | rightLineWidth = StaticLineBase.STATIC_LINE_TEXT_EDGE
172 | rightProportion = 0
173 | else:
174 | leftLineWidth = StaticLineBase.STATIC_LINE_TEXT_EDGE
175 | leftProportion = 0
176 | self.leftLine = wx.StaticLine(parent, wx.NewId(), wx.Point(0, 0), wx.Size(leftLineWidth, textSize.height),wx.LI_HORIZONTAL)
177 | self.rightLine = wx.StaticLine(parent, wx.NewId(), wx.Point(0, 0), wx.Size(rightLineWidth, textSize.height),wx.LI_HORIZONTAL)
178 | self.Add(self.leftLine, leftProportion, wx.ALL | wx.EXPAND, self.ITEM_BORDER_WIDTH)
179 | self.Add(self.staticText, 0, wx.ALL, self.ITEM_BORDER_WIDTH)
180 | self.Add(self.rightLine, rightProportion, wx.ALL | wx.EXPAND, 0)
181 | def Enable(self, bEnable):
182 | EnableSizer(self, bEnable)
183 |
--------------------------------------------------------------------------------
/FormUI/Frame.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | from Form import *
13 | import Queue
14 | from WorkThread import *
15 | from Builder import *
16 | from BuilderUtil import *
17 |
18 | def create(parent, builder, workQueue):
19 | return Frame(parent,builder, workQueue)
20 |
21 | [wxID_DIALOG1BUTTONOK, wxID_DIALOG1BUTTONCANCEL] = [wx.NewId() for _init_ctrls in range(2)]
22 |
23 | ##Frame,The Window of application
24 | class Frame(wx.Frame,FormCtrl):
25 | WINDOW_STATE_INIT = 0
26 | WINDOW_STATE_WORK = 1
27 | WINDOW_STATE_CLOSED = 2
28 | def initWindowPara(self):
29 | self.form = self.builder.form
30 |
31 | def _init_ctrls(self, prnt):
32 | self.initWindowPara()
33 | self.windowState = self.WINDOW_STATE_INIT
34 | #self.bCloseWindow = False
35 | self.notebook = None
36 | self.style = BuilderUtil.convertStyle(self.form.style)
37 | stylePara = self.__makeStylePara()
38 | wx.Frame.__init__(self, id=wx.NewId(), name='', parent=prnt,
39 | pos=wx.Point(self.form.windowPosX, self.form.windowPosY), size=wx.Size(self.form.windowWidth, self.form.windowHeight),
40 | style=stylePara, title=self.form.title)
41 | self.SetClientSize(wx.Size(self.form.windowWidth, self.form.windowHeight))
42 | self.Center(wx.BOTH)
43 | self.update(self.builder, True)
44 | self.windowHandler = WindowHandler(self)
45 |
46 | def __makeStylePara(self):
47 | if 'default' not in self.style.keys():
48 | stylePara = wx.DEFAULT_FRAME_STYLE
49 | else:
50 | stylePara = 0
51 |
52 | styleMap = {}
53 | styleMap['default'] = wx.DEFAULT_FRAME_STYLE
54 | styleMap['minimize_box'] = wx.MINIMIZE_BOX
55 | styleMap['maximize_box'] = wx.MAXIMIZE_BOX
56 | styleMap['system_menu'] = wx.SYSTEM_MENU
57 | styleMap['resize_box'] = wx.RESIZE_BOX
58 | styleMap['resize_border'] = wx.RESIZE_BORDER
59 | styleMap['stay_on_top'] = wx.STAY_ON_TOP
60 | styleMap['close_box'] = wx.CLOSE_BOX
61 | styleMap['iconize'] = wx.ICONIZE
62 |
63 | for (k, v) in self.style.items():
64 | if k not in styleMap.keys():
65 | continue
66 | if BuilderUtil.convertBool(v):
67 | stylePara = stylePara | styleMap[k]
68 | else:
69 | stylePara = stylePara & ~ styleMap[k]
70 |
71 | return stylePara
72 |
73 | def initDefaultSize(self, builder,parent):
74 | if wx.VERSION[0] < 3:
75 | mesureButton = wx.Button(parent, -1, "Mesure")
76 | Builder.DEFAULT_LINE_HEIGHT = mesureButton.GetDefaultSize().y
77 | mesureButton.Destroy()
78 | else:
79 | Builder.DEFAULT_LINE_HEIGHT = wx.Button.GetDefaultSize().y
80 | menuBar = wx.MenuBar()
81 | Builder.DEFAULT_MENUBAR_HEIGHT = menuBar.GetSize().y
82 | menuBar.Destroy()
83 |
84 | def __init__(self, parent, builder,workQueue):
85 | self.valueList = {}
86 | self.idPanelMap = {}
87 | self.initSuccess = True
88 | self.initDefaultSize(builder,parent)
89 | builder.format()
90 | self.builder = builder
91 | self.workQueue = workQueue
92 | self.handlerFinishQueue = Queue(1)
93 | self._init_ctrls(parent)
94 | EVT_RESULT(self, self.handlerWorkUIEvent)
95 | self.Bind(wx.EVT_CLOSE, self.OnFrameClose)
96 |
97 | def showMainForm(self):
98 | self.SetTitle(self.form.title)
99 | self.SetPosition(wx.Point(self.form.windowPosX, self.form.windowPosY))
100 | self.SetSize(wx.Size(self.form.windowWidth, self.form.windowHeight))
101 | self.SetClientSize(wx.Size(self.form.windowWidth, self.form.windowHeight))
102 | size = self.GetSize()
103 | FormCtrl.__init__(self, self.form, self.windowControl)
104 |
105 | def update(self, builder = None, updateWindow = False):
106 | if builder is not None:
107 | self.builder = builder
108 | if updateWindow:
109 | self.initWindowPara()
110 | if self.windowState == self.WINDOW_STATE_WORK:
111 | self.windowState = self.WINDOW_STATE_CLOSED
112 | self.DestroyForm()
113 | for (k,v) in builder.ctrlTypeRegist.items():
114 | gControlTypeRegister[k] = v
115 | self.windowControl = WindowControl(self.builder.handlerMap, self)
116 | self.showMainForm()
117 | self.windowState = self.WINDOW_STATE_WORK
118 |
119 | #The accelerator will triger EVT_MENU event
120 | for accelerator in self.windowControl.acceleratorTable:
121 | self.Bind(wx.EVT_MENU, self.onAccelerator, id=accelerator[2])
122 | acceltbl = wx.AcceleratorTable(self.windowControl.acceleratorTable)
123 |
124 | self.SetAcceleratorTable(acceltbl)
125 |
126 | def onAccelerator(self, event):
127 | self.windowControl.OnItemEvent(event)
128 |
129 | def onsubFormExit(self, workThread):
130 | pass
131 |
132 | def showForm(self, builder,workThread):
133 | form = create(None, builder, workThread.queue)
134 | if form.initSuccess:
135 | form.Show()
136 | wx.GetApp().SetTopWindow(form)
137 | workThread.start()
138 |
139 | #Call Form Handler,
140 | def CallFormHandler(self, id,eventType):
141 | if self.workQueue is not None:
142 | ctrlHandler = None
143 | if id in self.windowControl.handlerMap.keys():
144 | ctrlHandler = self.windowControl.handlerMap[id]
145 | if ctrlHandler is not None or self.builder.defaultHandler is not None:
146 | if ctrlHandler is not None:
147 | para = self.windowControl.makeReturnPara(id,eventType,ctrlHandler)
148 | self.workQueue.put([EVENT_TYPE_WINDOW_CONTROL, self.windowHandler, para], block=True, timeout=None)
149 | if self.builder.defaultHandler is not None:
150 | para = self.windowControl.makeReturnPara(id,eventType,self.builder.defaultHandler)
151 | self.workQueue.put([EVENT_TYPE_WINDOW_CONTROL, self.windowHandler, para], block=True, timeout=None)
152 |
153 | return True
154 | return False
155 |
156 | def handlerWorkUIEvent(self,msg):
157 | para = msg.data
158 | eventType = para['event']
159 | if eventType == EVENT_WORKTHREAD_UPDATE:
160 | self.update(para['builder'], para['updateWindow'])
161 | elif eventType == EVENT_WORKTHREAD_SHOWFORM:
162 | self.showForm(para['builder'], para['workThread'])
163 | elif eventType == EVENT_WORKTHREAD_CLOSE:
164 | self.Close()
165 | elif eventType == EVENT_WORKTHREAD_SHOW:
166 | self.Show(para['bShow'])
167 | wx.GetApp().SetTopWindow(self)
168 | elif eventType == EVENT_WORKTHREAD_ENABLE_ITEM:
169 | self.windowControl.enableCtrl(para['itemId'],para['bEnable'])
170 | wx.GetApp().SetTopWindow(self)
171 | elif eventType == EVENT_WORKTHREAD_SHOW_ITEM:
172 | self.windowControl.showCtrl(para['itemId'], para['bShow'])
173 | wx.GetApp().SetTopWindow(self)
174 | elif eventType == EVENT_WORKTHREAD_MESSAGE:
175 | self.windowControl.handlerItemMessage(para['itemId'], para['messageId'],para['messagePara'])
176 | elif eventType == EVENT_WORKTHREAD_ITEM_SET_VALUE:
177 | self.windowControl.setItemValue(para['itemId'], para['value'])
178 | elif eventType == EVENT_WORKTHREAD_HIGHLIGHT_ITEM:
179 | self.windowControl.highlightItem(para['itemId'])
180 | elif eventType == EVENT_WORKTHREAD_MESSAGEBOX:
181 | style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
182 | wx.MessageBox(message=para['message'], caption=para['caption'], style= style, parent=self)
183 | elif eventType == EVENT_WORKTHREAD_CONFIRM_MESSAGEBOX:
184 | style = wx.YES_NO | wx.ICON_INFORMATION | wx.STAY_ON_TOP
185 | if para['bWithCancelButton']:
186 | style = style | wx.CANCEL
187 | ret = wx.MessageBox(message=para['message'], caption=para['caption'], style= style, parent=self)
188 | else:
189 | pass
190 | if para and 'syncTask' in para.keys() and para['syncTask'] == True:
191 | self.handlerFinishQueue.put([EVENT_UITHREAD_HANDLER_FINISH], block=True, timeout=None)
192 |
193 | def OnFrameClose(self, event):
194 | self.windowState = self.WINDOW_STATE_CLOSED
195 | self.workQueue.put([EVENT_TYPE_APP_CLOSE, None, None], block=True, timeout=None)
196 | event.Skip()
197 |
--------------------------------------------------------------------------------
/FormUI/Builder.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | import copy
13 | import uuid
14 | from xml.dom.minidom import parse
15 | import xml.dom.minidom
16 | import wx
17 | from BuilderUtil import *
18 |
19 | #Form Builder
20 | class Form():
21 | def __init__(self):
22 | self.lines = []
23 | self.window_conf = {'width':300,'height': 400,
24 | 'title':"",'style':'default'}
25 | self.menubar = None
26 | def setWindowPara(self,windowConf):
27 | self.window_conf = dict(self.window_conf, **windowConf)
28 |
29 | def getWindowConfig(self,key):
30 | if key in self.window_conf.keys():
31 | return self.window_conf[key]
32 | else:
33 | return None
34 |
35 | def addLine(self,line):
36 | for lineCheck in self.lines:
37 | if lineCheck == line:
38 | return
39 | self.lines.append(line)
40 |
41 | def setCtrlAttribute(self, paraName, paraValue):
42 | self.window_conf[paraName] = paraValue
43 |
44 | def format(self, builder):
45 | self.windowWidth = int(self.getWindowConfig('width'))
46 | self.windowHeight = int(self.getWindowConfig('height'))
47 | self.windowPosX = self.getWindowConfig('pos_x')
48 | self.title = self.getWindowConfig('title')
49 | self.style = self.getWindowConfig('style')
50 | screenSize = wx.DisplaySize()
51 | if self.windowPosX == None:
52 | self.windowPosX = (screenSize[0] - self.windowWidth)/2
53 | else:
54 | self.windowPosX = int(self.windowPosX)
55 | self.windowPosY = self.getWindowConfig('pos_y')
56 | if self.windowPosY == None:
57 | self.windowPosY = (screenSize[1] - self.windowHeight)/2
58 | else:
59 | self.windowPosY = int(self.windowPosY)
60 |
61 | #NoteBook Builder
62 | class Notebook():
63 | def __init__(self, id):
64 | self.panels = []
65 | self.id = id
66 | self.height = -1
67 | def addPanel(self,panel):
68 | self.panels.append(panel)
69 | def getPanels(self):
70 | return self.panels
71 | def setCtrlAttribute(self, paraName, paraValue):
72 | if paraName == 'height':
73 | self.height = int(paraValue)
74 | def format(self,builder,lineWidth):
75 | for panel in self.panels:
76 | panel.format(builder, lineWidth)
77 |
78 | #Panel Builder
79 | class Panel():
80 | PANEL_EDGE_WIDTH = 1
81 | def __init__(self, panelId):
82 | self.panelId = panelId
83 | self.panelName = ""
84 | self.lines = []
85 | self.visible = True
86 | self.enable = True
87 | self.height = -1
88 | self.width = -1
89 | def addLine(self,line):
90 | self.lines.append(line)
91 | def getPanelName(self):
92 | return self.panelName
93 | def setCtrlAttribute(self, paraName, paraValue):
94 | if paraName == 'name':
95 | self.panelName = paraValue
96 | elif paraName == 'visible':
97 | self.visible = BuilderUtil.convertBool(paraValue)
98 | elif paraName == 'enable':
99 | self.enable = BuilderUtil.convertBool(paraValue)
100 | elif paraName == 'height':
101 | self.height = int(paraValue)
102 | def getLines(self):
103 | return self.lines
104 | def format(self,builder,lineWidth):
105 | if self.width == -1:
106 | self.width = lineWidth
107 | for line in self.lines:
108 | line.format(builder, self.width - Panel.PANEL_EDGE_WIDTH *2)
109 | #line Builder
110 | class Line():
111 | def __init__(self, lineId):
112 | self.items = []
113 | self.lineId = lineId
114 | self.visible = True
115 | self.enable = True
116 | self.align = 'left'
117 | self.expand = False
118 | self.height = 0
119 |
120 | def addItem(self,item):
121 | if item is not None:
122 | self.items.append(item)
123 |
124 | def setCtrlAttribute(self, paraName, paraValue):
125 | if paraName == 'align':
126 | self.align = str(paraValue)
127 | elif paraName == 'visible':
128 | self.visible = BuilderUtil.convertBool(paraValue)
129 | elif paraName == 'enable':
130 | self.enable = BuilderUtil.convertBool(paraValue)
131 | elif paraName == 'height':
132 | self.height = int(paraValue)
133 | elif paraName == 'expand':
134 | self.expand = BuilderUtil.convertBool(paraValue)
135 |
136 | def format(self,builder, lineWidth):
137 | for item in self.items:
138 | if 'height' not in item.keys():
139 | item['height'] = "%d" % Builder.DEFAULT_LINE_HEIGHT
140 | if int(item['height']) > self.height:
141 | self.height = int(item['height'])
142 | if 'visible' not in item.keys():
143 | item['visible'] = "true"
144 | #Menu Builder
145 | class Menu():
146 | def __init__(self, id):
147 | self.subMenus = []
148 | self.enable = True
149 | self.title = ""
150 | self.hint = ""
151 | self.id = id
152 | def addSubMenu(self, id, title, hint):
153 | subMenu = Menu(id)
154 | subMenu.title = title
155 | subMenu.hint = hint
156 | self.subMenus.append(subMenu)
157 | return subMenu
158 | def setCtrlAttribute(self, paraName, paraValue):
159 | if paraName == 'hint':
160 | self.hint = paraValue
161 | elif paraName == 'title':
162 | self.title = paraValue
163 | elif paraName == 'enable':
164 | self.enable = BuilderUtil.convertBool(paraValue)
165 |
166 | #The Buidler for Window
167 | class Builder():
168 | DEFAULT_LINE_HEIGHT = -1
169 | DEFAULT_MENUBAR_HEIGHT = -1
170 | DEFAULT_BUTTON_WIDTH = 100
171 | DEFAULT_LINE_WIDTH_EDGE = 5
172 | DEFAULT_LINE_HEIGHT_SPACE = 5
173 | def __init__(self):
174 | self.form = Form()
175 |
176 | self.__menu_list = []
177 | self.all_menu_items = []
178 | self.bShowMenu = False
179 |
180 | self.handlerMap = {}
181 | self.defaultHandler = None
182 |
183 | self.__idMap = {}
184 |
185 | self.blockWhenIdError = True
186 | self.ctrlTypeRegist = {}
187 |
188 | def setDefaultHandler(self, handler):
189 | self.defaultHandler =handler
190 |
191 | def setCtrlAttribute(self, id, paraName, paraValue):
192 | if id in self.__idMap.keys():
193 | itemList = self.__idMap[id]
194 | for item in itemList:
195 | if isinstance(item, Line) \
196 | or isinstance(item, Panel) \
197 | or isinstance(item, Notebook) \
198 | or isinstance(item, Form) \
199 | or isinstance(item, Menu):
200 | item.setCtrlAttribute(paraName, paraValue)
201 | else:
202 | item[paraName] = paraValue
203 | '''
204 | if isinstance(paraValue, bool):
205 | item[paraName] = 'true' if paraValue else 'false'
206 | elif isinstance(paraValue,list):
207 | item[paraName] = ''
208 | for itemCheck in paraValue:
209 | item[paraName] = paraValue
210 | else:
211 | if paraName == 'choices':
212 | item[paraName] = self.__getStrList(paraValue)
213 | elif item['type'] == 'check_list' and paraName == 'value':
214 | item[paraName] = self.__getStrList(paraValue)
215 | else:
216 | item[paraName] = str(paraValue)
217 | '''
218 |
219 | def setCtrlHandler(self, Id, handler):
220 | self.handlerMap[Id] = handler
221 |
222 | def format(self):
223 | if len(self.__menu_list) > 0:
224 | self.bShowMenu = True
225 | self.form.format(self)
226 |
227 | def __addIdMap(self, id, item):
228 | if id in self.__idMap.keys():
229 | itemList = self.__idMap[id]
230 | for itemCheck in itemList:
231 | if itemCheck == item:
232 | return
233 | else:
234 | self.__idMap[id] = []
235 | self.__idMap[id].append(item)
236 | def __getItem(self,id, type):
237 | ret = None
238 | if id in self.__idMap.keys():
239 | itemList = self.__idMap[id]
240 | for item in itemList:
241 | if isinstance(item, type):
242 | ret = item
243 | break
244 | return ret
245 | def updateValue(self, valueList):
246 | for (k, v) in valueList.items():
247 | self.setCtrlAttribute(k,'value', v)
248 |
249 | def copy(self):
250 | return copy.deepcopy(self)
251 |
252 | def __xmlGetAttribute(self,node,attribute,default=""):
253 | if node.hasAttribute(attribute):
254 | return node.getAttribute(attribute)
255 | return default
256 | def __getStrList(self, str):
257 | strList = str.split(';')
258 | retList = []
259 | for item in strList:
260 | retList.append(item.replace('[semicolon]', ';'))
261 | return retList
262 | def __xmlItemNode2Item(self,itemNode):
263 | item = {}
264 | if itemNode.nodeName == '#text':
265 | return None
266 | item['type'] = itemNode.nodeName
267 | if itemNode.attributes is not None:
268 | for attr in itemNode.attributes._attrs:
269 | item[attr] = itemNode.getAttribute(attr)
270 | #if attr == 'choices':
271 | # item[attr] = self.__getStrList(item[attr])
272 | #if item['type'] == 'check_list' and attr == 'value':
273 | # item[attr] = self.__getStrList(item[attr])
274 | return item
275 |
276 | def __xmlAddMenu(self,menu, menuNode):
277 | if menuNode.nodeName == 'menu' or menuNode.nodeName == 'menubar':
278 | for item in menuNode.childNodes:
279 | if item.nodeName == 'menu':
280 | menuId = self.__xmlGetAttribute(item, 'id', "%s" % uuid.uuid1())
281 | title = self.__xmlGetAttribute(item, 'title', '')
282 | hint = self.__xmlGetAttribute(item, 'hint', '')
283 | subMenu = menu.addSubMenu(menuId, title, hint)
284 | subMenu.enable = BuilderUtil.convertBool(self.__xmlGetAttribute(item, 'enable', True))
285 | subMenu.visible = BuilderUtil.convertBool(self.__xmlGetAttribute(item, 'visible', True))
286 | self.__addIdMap(menuId, subMenu)
287 | self.__xmlAddMenu(subMenu,item)
288 |
289 | def __xmlParseLine(self, lineNode):
290 | lineId = self.__xmlGetAttribute(lineNode, 'id', "%s" % uuid.uuid1())
291 | line = self.__getItem(lineId, Line)
292 | if line is None:
293 | line = Line(lineId)
294 | self.__addIdMap(lineId, line)
295 | line.enable = BuilderUtil.convertBool(self.__xmlGetAttribute(lineNode, 'enable', True))
296 | line.visible = BuilderUtil.convertBool(self.__xmlGetAttribute(lineNode, 'visible', True))
297 | line.height = int(self.__xmlGetAttribute(lineNode, 'height', -1))
298 | line.align = str(self.__xmlGetAttribute(lineNode, 'align', 'align'))
299 | line.expand = BuilderUtil.convertBool(self.__xmlGetAttribute(lineNode, 'expand', False))
300 | for itemNode in lineNode.childNodes:
301 | item = self.__xmlItemNode2Item(itemNode)
302 | if item is not None:
303 | if 'id' in item.keys():
304 | itemCheck = self.__getItem(item['id'], dict)
305 | if itemCheck is not None \
306 | and itemCheck['type'] != 'button' \
307 | and itemCheck['type'] != 'static' \
308 | and itemCheck['type'] != 'static_line':
309 | print('\033[1;31;40m' +"Error:Duplicated Id("+ item['id'] +"), Please fix it" + '\033[0m')
310 | if self.blockWhenIdError:
311 | raw_input("Press Enter key to continue...")
312 | self.__addIdMap(item['id'], item)
313 | line.addItem(item)
314 | return line
315 |
316 | def __xmlParsePanel(self, panelNode):
317 | panelId = self.__xmlGetAttribute(panelNode, 'id', "%s" % uuid.uuid1())
318 | panel = self.__getItem(panelId, Panel)
319 | if panel is None:
320 | panel = Panel(panelId)
321 | self.__addIdMap(panelId, panel)
322 | panel.panelName = self.__xmlGetAttribute(panelNode, 'name')
323 | panel.height = int(self.__xmlGetAttribute(panelNode, 'height', -1))
324 | panel.width = int(self.__xmlGetAttribute(panelNode, 'width', -1))
325 | panel.enable = BuilderUtil.convertBool(self.__xmlGetAttribute(panelNode, 'enable', True))
326 | panel.visible = BuilderUtil.convertBool(self.__xmlGetAttribute(panelNode, 'visible', True))
327 | #self.panels.append(panel)
328 | for lineNode in panelNode.childNodes:
329 | if lineNode.nodeName == "line":
330 | panel.addLine(self.__xmlParseLine(lineNode))
331 | return panel
332 |
333 | def __xmlParseNotebook(self, notebookNode):
334 | id = self.__xmlGetAttribute(notebookNode, 'id', "%s" % uuid.uuid1())
335 | notebook = self.__getItem(id, Notebook)
336 | if notebook is None:
337 | notebook = Notebook(id)
338 | notebook.height = int(self.__xmlGetAttribute(notebookNode, 'height', -1))
339 | self.__addIdMap(id, notebook)
340 | for panelNode in notebookNode.childNodes:
341 | if panelNode.nodeName == "panel":
342 | notebook.addPanel(self.__xmlParsePanel(panelNode))
343 | return notebook
344 |
345 | def loadLayout(self, file):
346 | self.__init__()
347 | self.mergeLayout(file)
348 |
349 | def mergeLayout(self, file):
350 | DOMTree = xml.dom.minidom.parse(file)
351 | Data = DOMTree.documentElement
352 | if Data.nodeName == 'form':
353 | formNode = Data
354 | if formNode.attributes is not None:
355 | for attr in formNode.attributes._attrs:
356 | self.form.window_conf[attr] = formNode.getAttribute(attr)
357 |
358 | for lineNode in formNode.childNodes:
359 | if lineNode.nodeName == "line":
360 | self.form.addLine(self.__xmlParseLine(lineNode))
361 | elif lineNode.nodeName == "panel":
362 | self.form.addLine(self.__xmlParsePanel(lineNode))
363 | elif lineNode.nodeName == "notebook":
364 | self.form.addLine(self.__xmlParseNotebook(lineNode))
365 |
366 | for menubarNode in Data.getElementsByTagName("menubar"):
367 | if self.form.menubar == None:
368 | self.form.menubar = Menu('')
369 | self.__xmlAddMenu(self.form.menubar, menubarNode)
370 |
371 | def registControlType(self, ctrlName, ctrlTypeRegist):
372 | self.ctrlTypeRegist[ctrlName] = ctrlTypeRegist
373 |
--------------------------------------------------------------------------------
/FormUI/FormControl.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 |
12 | from FormControlBase import *
13 | import wx.lib.scrolledpanel as scrolled
14 | import wx.lib.filebrowsebutton
15 |
16 |
17 | global gControlTypeRegister
18 | gControlTypeRegister = {}
19 |
20 | ###########################
21 | ##FormCtrol should implement the interfaces listed as below:
22 | ## def GetValue(self):
23 | ## def SetValue(self,value):
24 | ## def Enable(self,bEnable):
25 | ## def SetFocus(self):
26 | ## def onMessage(self, messageId, messagePara):
27 | ###########################
28 |
29 | class Static(wx.StaticText, FormControlBase):
30 | def __init__(self, item, parent, windowControl):
31 | FormControlBase.__init__(self, item,parent)
32 | para = FormControlUtil.makeCommonPara(item,parent)
33 | para['label'] = FormControlUtil.getLable(item)
34 | wx.StaticText.__init__(self,**para)
35 |
36 | def GetValue(self):
37 | return None
38 |
39 | def SetValue(self,value):
40 | pass
41 | gControlTypeRegister['static'] = Static
42 |
43 | class Choise(wx.Choice, FormControlBase):
44 | def __init__(self, item, parent, windowControl):
45 | para = FormControlUtil.makeCommonPara(item, parent)
46 | para['choices'] = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'choices', []))
47 | itemCtrl = wx.Choice.__init__(self,**para)
48 | FormControlBase.__init__(self, item,parent)
49 | windowControl.registItemHandler(self, para['id'],wx.EVT_CHOICE,'evt_choice')
50 |
51 | def GetValue(self):
52 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(self.item, 'choices', []))
53 | return choices[wx.Choice.GetSelection(self)]
54 |
55 | def SetValue(self,value):
56 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(self.item, 'choices', []))
57 | index = choices.index(value)
58 | if index >= 0:
59 | wx.Choice.Select(self,index)
60 |
61 | gControlTypeRegister['choise'] = Choise
62 |
63 |
64 | class Text(FormControlBase,wx.TextCtrl):
65 | def __init__(self, item, parent, windowControl):
66 | FormControlBase.__init__(self, item,parent)
67 | para = FormControlUtil.makeCommonPara(item,parent)
68 | if 'multi_line' in item.keys() and BuilderUtil.getItemValue(item, 'multi_line') == 'true':
69 | para['style'] = para['style'] | wx.TE_MULTILINE
70 | if 'password' in item.keys() and BuilderUtil.getItemValue(item, 'password') == 'true':
71 | para['style'] = para['style'] | wx.TE_PASSWORD
72 | para['value'] = BuilderUtil.getItemValue(item, 'value', '')
73 | wx.TextCtrl.__init__(self,**para)
74 |
75 | gControlTypeRegister['text'] = Text
76 |
77 |
78 | class StaticLine(StaticLineBase,FormControlBase):
79 | def __init__(self, item, parent, windowControl):
80 | FormControlBase.__init__(self, item, parent)
81 | para = FormControlUtil.makeCommonPara(item,parent)
82 | para['label'] = FormControlUtil.getLable(item)
83 | itemCtrl = StaticLineBase.__init__(self, **para)
84 | return itemCtrl
85 |
86 | def GetValue(self):
87 | return None
88 |
89 | def SetValue(self,value):
90 | pass
91 | gControlTypeRegister['static_line'] = StaticLine
92 |
93 | class CheckList(wx.CheckListBox,FormControlBase):
94 | def __init__(self, item, parent, windowControl):
95 | FormControlBase.__init__(self, item,parent)
96 | para = FormControlUtil.makeCommonPara(item,parent)
97 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'choices', []))
98 | para['choices'] = choices
99 | itemCtrl = wx.CheckListBox.__init__(self,**para)
100 | windowControl.registItemHandler(self, para['id'], wx.EVT_CHECKLISTBOX,'evt_checklistbox')
101 |
102 | def GetValue(self):
103 | checked_list = wx.CheckListBox.GetChecked(self)
104 | value = []
105 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(self.item, 'choices', []))
106 | for index in checked_list:
107 | value.append(choices[index])
108 | return value
109 |
110 | def SetValue(self,value):
111 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(self.item, 'choices', []))
112 | value = FormControlUtil.convertList(value)
113 | if len(choices) < 1:
114 | return
115 | default_check = []
116 | if value != '':
117 | for check_item in value:
118 | if check_item in choices:
119 | index = choices.index(check_item)
120 | default_check.append(index)
121 | wx.CheckListBox.SetChecked(self,default_check)
122 | gControlTypeRegister['check_list'] = CheckList
123 |
124 | class List(wx.ListBox, FormControlBase):
125 | def __init__(self, item, parent, windowControl):
126 | FormControlBase.__init__(self, item,parent)
127 | para = FormControlUtil.makeCommonPara(item,parent)
128 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'choices', []))
129 | para['choices'] = choices
130 | itemCtrl = wx.ListBox.__init__(self,**para)
131 | windowControl.registItemHandler(self, para['id'], wx.EVT_LISTBOX,'evt_listbox')
132 | windowControl.registItemHandler(self, para['id'], wx.EVT_LISTBOX_DCLICK, 'evt_listbox_dclick')
133 |
134 | def GetValue(self):
135 | return wx.ListBox.GetStringSelection(self)
136 |
137 | def SetValue(self, value):
138 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(self.item, 'choices', []))
139 | if value in choices:
140 | index = choices.index(value)
141 | wx.ListBox.SetSelection(self,index)
142 | gControlTypeRegister['list'] = List
143 |
144 | class RadioBox(wx.RadioBox, FormControlBase):
145 | def __init__(self, item, parent, windowControl):
146 | FormControlBase.__init__(self, item,parent)
147 | para = FormControlUtil.makeCommonPara(item,parent)
148 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'choices', []))
149 | para['choices'] = choices
150 | para['majorDimension'] = int(BuilderUtil.getItemValue(item, 'columns', '1'))
151 | para['style'] = para['style'] | wx.RA_SPECIFY_COLS
152 | itemCtrl = wx.RadioBox.__init__(self,**para)
153 | windowControl.registItemHandler(self, para['id'], wx.EVT_RADIOBOX,'evt_radiobox')
154 |
155 | def GetValue(self):
156 | return wx.RadioBox.GetStringSelection(self)
157 |
158 | def SetValue(self,value):
159 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(self.item, 'choices', []))
160 | if value in choices:
161 | index = choices.index(value)
162 | wx.RadioBox.SetSelection(self,index)
163 | gControlTypeRegister['radio_box'] = RadioBox
164 |
165 |
166 | class Check(wx.CheckBox, FormControlBase):
167 | def __init__(self, item, parent, windowControl):
168 | FormControlBase.__init__(self, item,parent)
169 | para = FormControlUtil.makeCommonPara(item,parent)
170 | para['label'] = FormControlUtil.getLable(item)
171 | itemCtrl = wx.CheckBox.__init__(self,**para)
172 | windowControl.registItemHandler(self, para['id'], wx.EVT_CHECKBOX,'evt_checkbox')
173 |
174 | def GetValue(self):
175 | return 'true' if wx.CheckBox.GetValue(self) else 'false'
176 |
177 | def SetValue(self,value):
178 | if FormControlUtil.conventBool(value):
179 | wx.CheckBox.SetValue(self,True)
180 | else:
181 | wx.CheckBox.SetValue(self,False)
182 | gControlTypeRegister['check'] = Check
183 |
184 |
185 | class ComboBox(wx.ComboBox, FormControlBase):
186 | def __init__(self, item, parent, windowControl):
187 | FormControlBase.__init__(self, item,parent)
188 | para = FormControlUtil.makeCommonPara(item,parent)
189 | choices = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'choices', []))
190 | para['choices'] = choices
191 | itemCtrl = wx.ComboBox.__init__(self,**para)
192 | value = BuilderUtil.getItemValue(item, 'value', '')
193 | if FormControlUtil.conventBool(value):
194 | itemCtrl.SetValue(value)
195 | elif len(choices) > 0:
196 | wx.ComboBox.SetValue(self,choices[0])
197 | gControlTypeRegister['combo_box'] = ComboBox
198 |
199 | class Date(wx.DatePickerCtrl,FormControlBase):
200 | def __init__(self, item, parent, windowControl):
201 | FormControlBase.__init__(self, item,parent)
202 | para = FormControlUtil.makeCommonPara(item,parent)
203 | para['style'] = para['style'] | wx.DP_SHOWCENTURY | wx.DP_DEFAULT
204 | itemCtrl = wx.DatePickerCtrl.__init__(self,**para)
205 |
206 | def GetValue(self):
207 | return wx.DatePickerCtrl.GetValue(self).FormatISODate()
208 |
209 | def SetValue(self,value):
210 | if value != "":
211 | dt = wx.DateTime()
212 | dt.ParseDate(value)
213 | wx.DatePickerCtrl.SetValue(self,dt)
214 | gControlTypeRegister['date'] = Date
215 |
216 |
217 | class Time(wx.lib.masked.timectrl.TimeCtrl,FormControlBase):
218 | def __init__(self, item, parent, windowControl):
219 | FormControlBase.__init__(self, item,parent)
220 | para = FormControlUtil.makeCommonPara(item,parent)
221 | para['display_seconds'] = True
222 | para['fmt24hr'] = True
223 | para['oob_color'] = wx.NamedColour('Yellow')
224 | para['useFixedWidthFont'] = True
225 | wx.lib.masked.timectrl.TimeCtrl.__init__(self,**para)
226 | gControlTypeRegister['time'] = Time
227 |
228 |
229 | class DateTime(FormControlBase,DateTimeBase):
230 | def __init__(self, item, parent, windowControl):
231 | FormControlBase.__init__(self, item,parent)
232 | para = FormControlUtil.makeCommonPara(item,parent)
233 | DateTimeBase.__init__(self,**para)
234 | gControlTypeRegister['datetime'] = DateTime
235 |
236 |
237 | class Button(FormControlBase,wx.Button):
238 | def __init__(self, item, parent, windowControl):
239 | FormControlBase.__init__(self, item,parent)
240 | para = FormControlUtil.makeCommonPara(item,parent)
241 | para['label'] = FormControlUtil.getLable(item)
242 | wx.Button.__init__(self,**para)
243 | windowControl.registItemHandler(self, para['id'], wx.EVT_BUTTON,'evt_button')
244 |
245 | def GetValue(self):
246 | return None
247 |
248 | def SetValue(self,value):
249 | pass
250 | gControlTypeRegister['button'] = Button
251 |
252 |
253 | class File(FormControlBase,wx.lib.filebrowsebutton.FileBrowseButtonWithHistory):
254 | def __init__(self, item, parent, windowControl):
255 | FormControlBase.__init__(self, item,parent)
256 | para = FormControlUtil.makeCommonPara(item,parent)
257 | para['buttonText'] = 'Browse'
258 | para['dialogTitle'] = 'Choose a file'
259 | para['fileMask'] = BuilderUtil.getItemValue(item, 'mark', "*")
260 | para['labelText'] = FormControlUtil.getLable(item)
261 | para['style'] = para['style'] | wx.TAB_TRAVERSAL
262 | para['startDirectory'] = '.'
263 | para['fileMode'] = wx.FD_SAVE
264 | para['toolTip'] = 'Type filename or click browse to choose file'
265 | wx.lib.filebrowsebutton.FileBrowseButtonWithHistory.__init__(self,**para)
266 | self.SetHistory(FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'choices')))
267 | windowControl.registItemHandler(self, para['id'],wx.EVT_BUTTON,'evt_button')
268 | gControlTypeRegister['file'] = File
269 |
270 |
271 | class Folder(FormControlBase,wx.lib.filebrowsebutton.DirBrowseButton):
272 | def __init__(self, item, parent, windowControl):
273 | FormControlBase.__init__(self, item,parent)
274 | para = FormControlUtil.makeCommonPara(item,parent)
275 | value = BuilderUtil.getItemValue(item, 'value', '')
276 | para['dialogTitle'] = 'Choose a folder'
277 | para['labelText'] = FormControlUtil.getLable(item)
278 | para['startDirectory'] = value
279 | para['style'] = para['style'] | wx.TAB_TRAVERSAL
280 | wx.lib.filebrowsebutton.DirBrowseButton.__init__(self,**para)
281 | gControlTypeRegister['folder'] = Folder
282 |
283 |
284 | class Folder(FormControlBase,wx.lib.filebrowsebutton.DirBrowseButton):
285 | def __init__(self, item, parent, windowControl):
286 | FormControlBase.__init__(self, item,parent)
287 | para = FormControlUtil.makeCommonPara(item,parent)
288 | value = BuilderUtil.getItemValue(item, 'value', '')
289 | para['dialogTitle'] = 'Choose a folder'
290 | para['labelText'] = FormControlUtil.getLable(item)
291 | para['startDirectory'] = value
292 | para['style'] = para['style'] | wx.TAB_TRAVERSAL
293 | wx.lib.filebrowsebutton.DirBrowseButton.__init__(self,**para)
294 | gControlTypeRegister['folder'] = Folder
295 |
296 | class MultiFiles(FormControlBase,MultiFolderFileBase):
297 | def __init__(self, item, parent, windowControl):
298 | FormControlBase.__init__(self, item,parent)
299 | para = FormControlUtil.makeCommonPara(item,parent)
300 | para['mask'] = BuilderUtil.getItemValue(item, 'mask', "*")
301 | para['bAddFile'] = True
302 | para['bAddFolder'] = False
303 | value = BuilderUtil.getItemValue(item, 'value', '')
304 | MultiFolderFileBase.__init__(self,**para)
305 | gControlTypeRegister['multi_files'] = MultiFiles
306 |
307 |
308 | class MultiFolders(FormControlBase,MultiFolderFileBase):
309 | def __init__(self, item, parent, windowControl):
310 | FormControlBase.__init__(self, item,parent)
311 | para = FormControlUtil.makeCommonPara(item,parent)
312 | para['mask'] = BuilderUtil.getItemValue(item, 'mask', "*")
313 | para['bAddFile'] = False
314 | para['bAddFolder'] = True
315 | value = BuilderUtil.getItemValue(item, 'value', '')
316 | MultiFolderFileBase.__init__(self,**para)
317 | gControlTypeRegister['multi_folders'] = MultiFolders
318 |
319 |
320 | class MultiFolersFiles(FormControlBase,MultiFolderFileBase):
321 | def __init__(self, item, parent, windowControl):
322 | FormControlBase.__init__(self, item,parent)
323 | para = FormControlUtil.makeCommonPara(item,parent)
324 | para['mask'] = BuilderUtil.getItemValue(item, 'mask', "*")
325 | para['bAddFile'] = True
326 | para['bAddFolder'] = True
327 | MultiFolderFileBase.__init__(self,**para)
328 | gControlTypeRegister['multi_folders_files'] = MultiFolersFiles
329 |
330 | class Table(FormControlBase,wx.ListCtrl):
331 | def __init__(self, item, parent, windowControl):
332 | FormControlBase.__init__(self, item,parent)
333 | para = FormControlUtil.makeCommonPara(item,parent)
334 | para['style'] = para['style'] | wx.LC_REPORT | wx.BORDER_SUNKEN
335 | itemCtrl = wx.ListCtrl.__init__(self,**para)
336 | tableList = BuilderUtil.getItemValue(item, 'data', [])
337 | columnList = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'columns', []))
338 | columnWidthList = FormControlUtil.convertList(BuilderUtil.getItemValue(item, 'columns_width', []))
339 | columnIndex = 0
340 | for column in columnList:
341 | width = -1
342 | if columnIndex < len(columnWidthList):
343 | width = int(columnWidthList[columnIndex])
344 | self.InsertColumn(columnIndex, column, width=width)
345 | columnIndex = columnIndex + 1
346 | item['indexMap'] = {}
347 | item['idMap'] = {}
348 | for line in tableList:
349 | index = self.GetItemCount()
350 | item['indexMap'][index] = line['id']
351 | item['idMap'][line['id']] = str(index)
352 | lineItems = FormControlUtil.convertList(line['items'])
353 | self.InsertStringItem(index, '')
354 | columnIndex = 0
355 | for lineitem in lineItems:
356 | self.SetStringItem(index, columnIndex, lineitem)
357 | columnIndex = columnIndex + 1
358 | windowControl.registItemHandler(self, para['id'],wx.EVT_LIST_ITEM_SELECTED,'evt_list_item_selected')
359 | windowControl.registItemHandler(self, para['id'],wx.EVT_LIST_ITEM_DESELECTED,'evt_list_item_deselected')
360 | def GetValue(self):
361 | select = wx.ListCtrl.GetFirstSelected(self)
362 | if select < 0:
363 | return None
364 | ret = []
365 | while select >= 0:
366 | ret.append(self.item['indexMap'][select])
367 | select = wx.ListCtrl.GetNextSelected(self,select)
368 | return ret
369 | def SetValue(self,value):
370 | valueList = FormControlUtil.convertList(value)
371 | for value in valueList:
372 | index = self.item['idMap'][str(value)]
373 | wx.ListCtrl.SetItemState(self,long(index), wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
374 | gControlTypeRegister['table'] = Table
375 |
376 |
377 | class Tree(FormControlBase,wx.TreeCtrl):
378 | def AddTree(self, parent,Node, idMap):
379 | if parent is None:
380 | nodeCtrl = self.AddRoot(Node['title'])
381 | else:
382 | nodeCtrl = self.AppendItem(parent, Node['title'])
383 | self.SetItemData(nodeCtrl, wx.TreeItemData(Node['id']))
384 | idMap[Node['id']] = nodeCtrl
385 | if Node['subNodes'] != []:
386 | for subNode in Node['subNodes']:
387 | self.AddTree(nodeCtrl, subNode,idMap)
388 |
389 | def __init__(self, item, parent, windowControl):
390 | FormControlBase.__init__(self, item,parent)
391 | para = FormControlUtil.makeCommonPara(item,parent)
392 | para['style'] = para['style'] | wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE
393 | itemCtrl = wx.TreeCtrl.__init__(self,**para)
394 | treeData = BuilderUtil.getItemValue(item, 'data', [])
395 | item['idMap'] = {}
396 | self.AddTree(None, treeData, item['idMap'])
397 | windowControl.registItemHandler(self, para['id'],wx.EVT_TREE_SEL_CHANGED,'evt_tree_sel_changed')
398 | def GetValue(self):
399 | selects = wx.TreeCtrl.GetSelections(self)
400 | ret = []
401 | for select in selects:
402 | ret.append(wx.TreeCtrl.GetItemData(self,select).GetData())
403 | return ret
404 | def SetValue(self,value):
405 | valueList = FormControlUtil.convertList(value)
406 | for value in valueList:
407 | valueId = self.item['idMap'][str(value)]
408 | wx.TreeCtrl.SelectItem(self,valueId)
409 | gControlTypeRegister['tree'] = Tree
--------------------------------------------------------------------------------
/FormUI/Form.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | ## Copyright 2012, En7788.com, Inc. All rights reserved.
3 | ##
4 | ## FormUI is a easy used GUI framwork for python, which is based on wxpython.
5 | ## FormUI is a free software: you can redistribute it and/or modify it under
6 | ## the terms of version 3 of the GNU Lesser General Public License as
7 | ## published by the Free Software Foundation.
8 | ##
9 | ## You should have received a copy of the GNU Lesser General Public License
10 | ## along with AndBug. If not, see .
11 | #from CommonCtrl import *
12 | import wx.lib.filebrowsebutton
13 | import Queue
14 | from FormControl import *
15 | from WorkThread import *
16 | from Builder import *
17 |
18 | EVT_RESULT_ID = wx.NewId()
19 |
20 | def EVT_RESULT(win, func):
21 | """Define Result Event."""
22 | win.Connect(-1, -1, EVT_RESULT_ID, func)
23 |
24 | ##Result Event,used to postEvent to window
25 | class ResultEvent(wx.PyEvent):
26 | def __init__(self, data):
27 | wx.PyEvent.__init__(self)
28 | self.SetEventType(EVT_RESULT_ID)
29 | self.data = data
30 |
31 | ##WindowControl, Deseperate Control From Frame
32 | class WindowControl():
33 | def __init__(self, handlerMap, window):
34 | self.window = window
35 | self.handlerMap = handlerMap
36 | self.eventId2IdMap = {} #windowID: item_Id
37 | self.id2EventIdMap = {}
38 | self.id2CtrlMap = {}
39 | self.id2ItemMap = {}
40 | self.valueItems = []
41 | self.eventTypeNameMap = {}
42 | self.acceleratorTable = []
43 | #self.window.SetAcceleratorTable(accelTbl)
44 |
45 | def __registAccelerator(self, accelerator, ctrlId):
46 | accelerator = accelerator.lower()
47 | accelerator = accelerator.split('+')
48 | ctrlKey = wx.ACCEL_NORMAL
49 | normalKey = ''
50 | for item in accelerator:
51 | if item == 'ctrl':
52 | if ctrlKey == wx.ACCEL_NORMAL:
53 | ctrlKey = wx.ACCEL_CTRL
54 | else:
55 | ctrlKey = ctrlKey | wx.ACCEL_CTRL
56 | elif item == 'alt':
57 | if ctrlKey == wx.ACCEL_NORMAL:
58 | ctrlKey = wx.ACCEL_ALT
59 | else:
60 | ctrlKey = ctrlKey | wx.ACCEL_ALT
61 | elif item == 'shift':
62 | if ctrlKey == wx.ACCEL_NORMAL:
63 | ctrlKey = wx.ACCEL_SHIFT
64 | else:
65 | ctrlKey = ctrlKey | wx.ACCEL_SHIFT
66 | else:
67 | normalKey = item
68 |
69 | self.acceleratorTable.append((ctrlKey, int(ord(normalKey)), ctrlId))
70 |
71 | def registItem(self, id, eventId, item, control):
72 | if item is not None:
73 | if id not in self.id2ItemMap.keys():
74 | self.id2ItemMap[id] = []
75 | self.id2ItemMap[id].append(item)
76 | #if item['type'] != 'static' and item['type'] != 'static_line' and item['type'] != 'button':
77 | self.valueItems.append(item)
78 |
79 | if id not in self.id2CtrlMap.keys():
80 | self.id2CtrlMap[id] = []
81 | self.id2CtrlMap[id].append(control)
82 |
83 | if item != None:
84 | accelerator = FormControlUtil.getAccelerator(item)
85 | if accelerator is not None:
86 | self.__registAccelerator(accelerator, eventId)
87 |
88 | if eventId is not None:
89 | self.eventId2IdMap[eventId] = id
90 | self.id2EventIdMap[id] = eventId
91 |
92 | def registItemHandler(self, ctrl, eventId,eventType,eventTypeName=''):
93 | self.eventTypeNameMap[eventType.typeId] = eventTypeName
94 | ctrl.Bind(eventType, self.OnItemEvent, id = eventId)
95 |
96 | def updateResult(self, valueList):
97 | global gControlTypeRegister
98 | for item in self.valueItems:
99 | value = item['control'].GetValue()
100 | if value is not None:
101 | valueList[item['id']] = value
102 |
103 | def setItemValue(self,itemId, value):
104 | if itemId in self.id2CtrlMap.keys():
105 | ctrlList =self.id2CtrlMap[itemId]
106 | for ctrl in ctrlList:
107 | ctrl.SetValue(value)
108 |
109 | def enableCtrl(self,itemId, bEnable):
110 | if itemId in self.id2CtrlMap.keys():
111 | ctrlList =self.id2CtrlMap[itemId]
112 | for ctrl in ctrlList:
113 | ctrl.Enable(bEnable)
114 |
115 | def updateLayout(self, ctrl):
116 | if hasattr(ctrl, 'Layout'):
117 | ctrl.Layout()
118 | if isinstance(ctrl, PanelCtrl) or isinstance(ctrl,wx.Frame):
119 | return
120 | if hasattr(ctrl, 'parent'):
121 | self.updateLayout(ctrl.parent)
122 |
123 | def showCtrl(self,itemId, bShow):
124 | if itemId in self.id2CtrlMap.keys():
125 | ctrlList =self.id2CtrlMap[itemId]
126 | for ctrl in ctrlList:
127 | ctrl.Show(bShow)
128 | self.updateLayout(ctrl)
129 | #self.window.Layout()
130 |
131 | def handlerItemMessage(self,itemId, messageId, messagePara):
132 | if itemId not in self.id2ItemMap.keys():
133 | return
134 |
135 | itemList = self.id2ItemMap[itemId]
136 | for item in itemList:
137 | self.window.handlerReturn = item['control'].onMessage(messageId, messagePara)
138 |
139 | def highlightItem(self,itemId):
140 | if not itemId in self.id2CtrlMap.keys():
141 | return
142 | ctrlList = self.id2CtrlMap[itemId]
143 | for ctrl in ctrlList:
144 | if isinstance(ctrl, PanelCtrl):
145 | ctrl.noteboolCtrl.SetSelection(ctrl.panelIndex)
146 | break
147 | elif isinstance(ctrl, LineCtrl):
148 | panel = ctrl.parent
149 | if isinstance(panel, PanelCtrl):
150 | panel.noteboolCtrl.SetSelection(panel.panelIndex)
151 | ctrl.highLight()
152 | break
153 | elif isinstance(ctrl, wx.Notebook):
154 | pass
155 | else:
156 | line = ctrl.parent
157 | if hasattr(line, 'parent'):
158 | panel = line.parent
159 | if isinstance(panel, PanelCtrl) and panel.panelIndex != None:
160 | panel.noteboolCtrl.SetSelection(panel.panelIndex)
161 | ctrl.SetFocus()
162 |
163 | def makeReturnPara(self, eventId, eventType,handler):
164 | para = HandlerPara(eventId, eventType,handler)
165 | self.updateResult(para.valueList)
166 | return para
167 |
168 | def OnItemEvent(self, event):
169 | if self.window.windowState != self.window.WINDOW_STATE_WORK:
170 | return
171 | if event.Id in self.eventId2IdMap.keys():
172 | id = self.eventId2IdMap[event.Id]
173 | if id != None and id != '':
174 | self.window.CallFormHandler(id,self.eventTypeNameMap[event.EventType])
175 |
176 | #Todo:Notebook,Panel,Line Refactored by Composite Pattern
177 | ##The Base Class of Ctrl
178 | class CtrlBase():
179 | def __init__(self,windowControl,form):
180 | self.windowControl = windowControl
181 | self.form = form
182 | pass
183 | def createLine(self, line):
184 | lineSizer = LineCtrl(self, self.windowControl)
185 | self.windowSizer.AddSpacer(Builder.DEFAULT_LINE_HEIGHT_SPACE)
186 | lineSizer.initCtrls(self, line)
187 | flag = wx.EXPAND | wx.ALL
188 | if line.align == 'center':
189 | flag = flag | wx.ALIGN_CENTER
190 | elif line.align == 'right':
191 | flag = flag | wx.ALIGN_RIGHT
192 | elif line.align == 'left':
193 | flag = flag | wx.ALIGN_LEFT
194 | proportion = 0
195 | if line.expand:
196 | proportion = 1
197 | self.windowSizer.AddWindow(lineSizer, proportion, border=Builder.DEFAULT_LINE_WIDTH_EDGE, flag=flag)
198 | # if line.lineId != "":
199 | # self.idLineMap[line.lineId] = lineSizer
200 | if line.visible == False:
201 | lineSizer.Show(False)
202 | def createPanel(self,panel):
203 | eventId = wx.NewId()
204 | panelControl = PanelCtrl(id=eventId, name=panel.panelId,
205 | parent=self,
206 | pos=wx.Point(0, 0),
207 | size=wx.Size(self.form.windowWidth, panel.height),
208 | lines=panel.getLines(),form=self.form,
209 | style=wx.TAB_TRAVERSAL, windowControl=self.windowControl
210 | )
211 | self.windowControl.registItem(panel.panelId, eventId, None, panelControl)
212 | proportion = 1
213 | if panel.height >= 0:
214 | proportion = 0
215 | self.windowSizer.AddWindow(panelControl, proportion, border=0, flag=wx.ALL | wx.EXPAND)
216 | if panel.visible is False:
217 | panelControl.Show(False)
218 | if panel.enable is False:
219 | panelControl.Enable(False)
220 | panelControl.panelIndex = None
221 | panelControl.id = panel.panelId
222 | return panelControl
223 | def createNotebook(self, notebook):
224 | eventId = wx.NewId()
225 | notebookCtrl = wx.Notebook(id=eventId, name=notebook.id,
226 | parent=self,
227 | pos=wx.Point(0, 0), size=wx.Size(self.form.windowWidth, notebook.height),
228 | style=0)
229 | self.windowControl.registItem(notebook.id, eventId, None, notebookCtrl)
230 | proportion = 1
231 | if notebook.height >= 0:
232 | proportion = 0
233 | self.windowSizer.AddWindow(notebookCtrl, proportion, border=0, flag=wx.ALL | wx.EXPAND)
234 | panels = notebook.getPanels()
235 | panelIndex = 0
236 | for panel in panels:
237 | eventId = wx.NewId()
238 | panelControl = PanelCtrl(id=eventId, name=panel.panelId,
239 | parent=notebookCtrl,
240 | pos=wx.Point(0, 0),
241 | size=wx.Size(self.form.windowWidth, notebook.height),
242 | lines=panel.getLines(),form=self.form,
243 | style=wx.TAB_TRAVERSAL, windowControl=self.windowControl
244 | )
245 | self.windowControl.registItem(panel.panelId, eventId, None, panelControl)
246 | #self.idPanelMap[panel.panelId] = panelControl
247 | if panel.visible is False:
248 | panelControl.Show(False)
249 | if panel.enable is False:
250 | panelControl.Enable(False)
251 | notebookCtrl.AddPage(panelControl, panel.panelName)
252 | panelControl.panelIndex = panelIndex
253 | panelControl.noteboolCtrl = notebookCtrl
254 | panelIndex += 1
255 | panelControl.id = panel.panelId
256 | #self.panelList.append(panelControl)
257 |
258 | def showWindow(self,lines):
259 | edge = 5
260 | self.lines = lines
261 | self.windowSizer = wx.BoxSizer(orient=wx.VERTICAL)
262 | self.viewHeight = edge
263 | self.lineNum = 0
264 | for line in self.lines:
265 | if isinstance(line, Line):
266 | self.createLine(line)
267 | if isinstance(line, Panel):
268 | self.createPanel(line)
269 | if isinstance(line, Notebook):
270 | self.createNotebook(line)
271 | self.SetSizer(self.windowSizer,True)
272 | self.SetAutoLayout(1)
273 | self.Layout()
274 | if isinstance(self, PanelCtrl):
275 | self.SetupScrolling()
276 |
277 |
278 | def showMenu(self):
279 | menubarInfo = self.form.menubar
280 | if menubarInfo is None:
281 | return
282 | self.menuBar = wx.MenuBar()
283 | self.menuIdCtrlmap = {}
284 | self.menuCtrlIdMap = {}
285 | for submenuInfo in menubarInfo.subMenus:
286 | menu, type = self.createMenu(None, submenuInfo)
287 | self.menuBar.Append(menu, submenuInfo.title)
288 |
289 | self.menuBar.Show()
290 | self.SetMenuBar(self.menuBar)
291 |
292 | for submenuInfo in menubarInfo.subMenus:
293 | self.updateMenuEnable(submenuInfo)
294 |
295 | def createMenu(self, currentMenu, menuInfo):
296 | eventId = wx.NewId()
297 | if len(menuInfo.subMenus) > 0 or currentMenu == None:
298 | menu = wx.Menu()
299 | for submenuInfo in menuInfo.subMenus:
300 | submenu,type=self.createMenu(menu, submenuInfo)
301 | if type == 'menu':
302 | menu.AppendMenu(eventId,submenuInfo.title,submenu)
303 | self.windowControl.registItem(menuInfo.id, eventId, None, None)
304 | else:
305 | menu.AppendItem(submenu)
306 | return menu,'menu'
307 | else:
308 | menuInfo.title = menuInfo.title.replace('\\t', '\t')
309 | menuItem = wx.MenuItem(currentMenu, eventId, menuInfo.title, menuInfo.hint)
310 | self.windowControl.registItem(menuInfo.id, eventId, None, menuItem)
311 | self.windowControl.registItemHandler(self, eventId, wx.EVT_MENU, 'evt_menu')
312 | return menuItem,'item'
313 |
314 | def updateMenuEnable(self, menuInfo):
315 | if len(menuInfo.subMenus) > 0:
316 | if menuInfo.enable == False and menuInfo.id != '':
317 | if menuInfo.id in self.windowControl.id2EventIdMap.keys():
318 | self.menuBar.Enable(self.windowControl.id2EventIdMap[menuInfo.id], False)
319 | for subMenuInfo in menuInfo.subMenus:
320 | self.updateMenuEnable(subMenuInfo)
321 | else:
322 | if menuInfo.enable == False:
323 | if menuInfo.id in self.windowControl.id2EventIdMap.keys():
324 | self.menuBar.Enable(self.windowControl.id2EventIdMap[menuInfo.id], False)
325 |
326 | ##Line Ctrl
327 | ##Ctrl Must Put in Line Ctrl
328 | class LineCtrl(wx.BoxSizer):
329 | def __init__(self,parent, windowControl):
330 | wx.BoxSizer.__init__(self,wx.HORIZONTAL)
331 | self.windowControl = windowControl
332 | self.parent = parent
333 | def createMultiFolderFileControl(self, item,value,itemWidth, itemHeight,bAddFile,bAddFolder):
334 | item['control'] = MultiFolderFile(parent=self.parent,
335 | pos=wx.Point(0, 0),
336 | size=wx.Size(itemWidth, itemHeight),
337 | mask=BuilderUtil.getItemValue(item, 'mask', '*'),
338 | bAddFile=bAddFile, bAddFolder=bAddFolder)
339 | if value != "":
340 | item['control'].SetValue(value)
341 | #self.valueItems.append(item)
342 | def getAlign(self,item):
343 | if 'align' in item.keys():
344 | alignText = BuilderUtil.getItemValue(item,'align','left')
345 | if alignText == 'center':
346 | return wx.ALIGN_CENTER
347 | elif alignText == 'right':
348 | return wx.ALIGN_RIGHT
349 | elif alignText == 'left' :
350 | return wx.ALIGN_LEFT
351 | return 0
352 |
353 | def createItem(self, lineSizer, item):
354 | global gControlTypeRegister
355 | if item['type'] in gControlTypeRegister.keys():
356 | item['control'] = gControlTypeRegister[item['type']](item, self.parent,self.windowControl)
357 | else:
358 | return
359 |
360 | if 'value' in item.keys() and item['value'] != '':
361 | item['control'].SetValue(item['value'])
362 |
363 | if 'visible' in item.keys():
364 | if item['visible'] == 'false':
365 | item['control'].Show(False)
366 | else:
367 | item['control'].Show(True)
368 |
369 | if 'enable' in item.keys():
370 | if BuilderUtil.getItemValue(item, 'enable', 'true') == 'true':
371 | item['control'].Enable(True)
372 | else:
373 | item['control'].Enable(False)
374 | #if 'id' in item.keys():
375 | # self.idItemMap[item['id']] = item
376 | item['parent'] = self
377 | proportion = 1
378 | if 'width' in item.keys() and int(item['width']) > 0:
379 | proportion = 0
380 | self.Add(item['control'], proportion, wx.EXPAND)
381 |
382 | if 'id' in item.keys():
383 | self.windowControl.registItem(item['id'], item['event_id'], item, item['control'])
384 | return True
385 | def initCtrls(self, parent, line):
386 | self.parent = parent
387 | for item in line.items:
388 | self.createItem(self, item)
389 | def Enable(self, bEnable):
390 | EnableSizer(self, bEnable)
391 | def Show(self, bShow):
392 | self.ShowItems(bShow)
393 | def highLight(self):
394 | children = self.GetChildren()
395 | for child in children:
396 | widget = child.GetWindow()
397 | if isinstance(widget, wx.BoxSizer):
398 | continue
399 | elif not isinstance(widget,wx.StaticText) and not isinstance(widget,StaticLine):
400 | widget.SetFocus()
401 |
402 | ##Panel
403 | class PanelCtrl(scrolled.ScrolledPanel,CtrlBase):
404 | def __init__(self, parent, id, pos, size, style, name,lines,form,windowControl):
405 | #scrolled.ScrolledPanel.__init__(self, parent, -1)
406 | self.form = form
407 | CtrlBase.__init__(self, windowControl,form)
408 | scrolled.ScrolledPanel.__init__(self, style=style, name=name,
409 | parent=parent, pos=pos, id=id,
410 | size=size)
411 | self.parent = self
412 | self.showWindow(lines)
413 |
414 | #Form Ctrl
415 | class FormCtrl(CtrlBase):
416 | def __init__(self,form, windowControl):
417 | CtrlBase.__init__(self, windowControl, form)
418 | self.menuBar = None
419 | self.showMenu()
420 | self.showWindow(form.lines)
421 |
422 | def DestroyForm(self):
423 | self.windowSizer.DeleteWindows()
424 | if self.menuBar != None:
425 | self.SetMenuBar(None)
426 | self.Layout()
427 |
428 | ##Handler Para
429 | ##The Menu,Ctrl can Set Handler, The Handler will be called when click or other event
430 | ##The Handler Para will be passed to Handler, from which Handler can get ctrl value
431 | class HandlerPara():
432 | def __init__(self, eventId,eventType,handler):
433 | self.valueList = {}
434 | self.eventId = eventId
435 | self.eventType = eventType
436 | self.handler = handler
437 |
438 | def getValue(self,id):
439 | if id in self.valueList.keys():
440 | return self.valueList[id]
441 | return None
442 | def getEventId(self):
443 | return self.eventId
444 | def getEventType(self):
445 | return self.eventType
446 |
447 | ##Handler Para
448 | ##The Menu,Ctrl can Set Handler, The Handler will be called when click or other event
449 | ##WindowHandler will be passed to Handler, Handler can control the window by WindowHandler
450 | class WindowHandler():
451 | def __init__(self, window):
452 | self.window = window
453 | self.windowClosed = False
454 | self.returnOk = False
455 |
456 | def __setWaitHandler(self,para):
457 | para['syncTask'] = True
458 | self.window.handlerReturn = None
459 |
460 | def __waitHandlerFinish(self):
461 | try:
462 | task = self.window.handlerFinishQueue.get(block=True)
463 | except Queue.Empty:
464 | return
465 | self.window.handlerFinishQueue.task_done()
466 | return self.window.handlerReturn
467 |
468 | def closeWindow(self, returnOk = True):
469 | self.window.windowState = self.window.WINDOW_STATE_CLOSED
470 | self.returnOk = True
471 | para = {}
472 | para['event'] = EVENT_WORKTHREAD_CLOSE
473 | wx.PostEvent(self.window, ResultEvent(para))
474 |
475 | def showWindow(self, bShow):
476 | para = {}
477 | para['bShow'] = bShow
478 | para['event'] = EVENT_WORKTHREAD_SHOW
479 | wx.PostEvent(self.window, ResultEvent(para))
480 |
481 | def enableCtrl(self, itemId, bEnable):
482 | para = {}
483 | para['itemId'] = itemId
484 | para['bEnable'] = bEnable
485 | para['event'] = EVENT_WORKTHREAD_ENABLE_ITEM
486 | wx.PostEvent(self.window, ResultEvent(para))
487 |
488 | def showCtrl(self, itemId, bShow):
489 | para = {}
490 | para['itemId'] = itemId
491 | para['bShow'] = bShow
492 | para['event'] = EVENT_WORKTHREAD_SHOW_ITEM
493 | wx.PostEvent(self.window, ResultEvent(para))
494 |
495 | def setValue(self,itemId, value):
496 | para = {}
497 | para['itemId'] = itemId
498 | para['value'] = value
499 | para['event'] = EVENT_WORKTHREAD_ITEM_SET_VALUE
500 | wx.PostEvent(self.window, ResultEvent(para))
501 |
502 | def update(self, builder, updateWindow=True):
503 | para = {}
504 | para['builder'] = builder
505 | para['updateWindow'] = updateWindow
506 | para['event'] = EVENT_WORKTHREAD_UPDATE
507 | wx.PostEvent(self.window, ResultEvent(para))
508 |
509 | def showForm(self,builder, bModule=False):
510 | para = {}
511 | para['builder'] = builder
512 | waitQueue = Queue(1)
513 | para['event'] = EVENT_WORKTHREAD_SHOWFORM
514 | workThread = SubFormThread(waitQueue = waitQueue)
515 | para['workThread'] = workThread
516 | wx.PostEvent(self.window, ResultEvent(para))
517 | if bModule:
518 | try:
519 | task = waitQueue.get(block=True)
520 | except Queue.Empty:
521 | pass
522 | waitQueue.task_done()
523 | return workThread.returnState, workThread.valueList
524 |
525 | def sendMessage(self,itemId,messageId,messagePara):
526 | para = {}
527 | para['itemId'] = itemId
528 | para['event'] = EVENT_WORKTHREAD_MESSAGE
529 | para['messageId'] = messageId
530 | para['messagePara'] = messagePara
531 | self.__setWaitHandler(para)
532 | wx.PostEvent(self.window, ResultEvent(para))
533 | ret = self.__waitHandlerFinish()
534 | return ret
535 |
536 | def messageBox(self,message, caption):
537 | para = {}
538 | para['message'] = message
539 | para['caption'] = caption
540 | self.__setWaitHandler(para)
541 | para['event'] = EVENT_WORKTHREAD_MESSAGEBOX
542 | wx.PostEvent(self.window, ResultEvent(para))
543 | self.__waitHandlerFinish()
544 |
545 | def confirmMessageBox(self,message, caption, bWithCancelButton=False):
546 | para = {}
547 | para['message'] = message
548 | para['caption'] = caption
549 | para['bWithCancelButton'] = bWithCancelButton
550 | self.__setWaitHandler(para)
551 | para['event'] = EVENT_WORKTHREAD_CONFIRM_MESSAGEBOX
552 | wx.PostEvent(self.window, ResultEvent(para))
553 | ret = self.__waitHandlerFinish()
554 | if ret == wx.ID_YES:
555 | return 'yes'
556 | elif ret == wx.ID_NO:
557 | return 'no'
558 | else:
559 | return 'cancel'
560 |
561 | def highlightItem(self,itemId):
562 | #self.window.highlightItem(itemId)
563 | para = {}
564 | para['itemId'] = itemId
565 | para['event'] = EVENT_WORKTHREAD_HIGHLIGHT_ITEM
566 | wx.PostEvent(self.window, ResultEvent(para))
567 |
568 | def getBuilder(self):
569 | return self.window.builder
570 |
--------------------------------------------------------------------------------