Robert Turner

Email: <rjturner AT SPAMFREE ucsd DOT edu>

Table Of Contents:

ToDo:

  • position things in the center using row and position so that it plays nicely when panes are hidden
  • add a window menu for showing and hiding panes
  • refactor ModelViewer

  • sphinx! get it up and working, get command documentation, start up documentation, wx documentation, and code generated documentation up
  • the filter list "By ..." commands should not be selectable
  • get the mesh commands to work first
  • get the bar to synchronize properly
  • get the database to cache models that it downloads
  • get file commands next
  • add a build toolbar function similar to the build menubar function
  • filters
  • then fitting, biomechanics, and electrophysiology
  • values.setCoordinateSystem(values.getCoordinateSystem()+1)

  • finish ObjectManagerForm

  • implement ResetClient, ResetServer, and ResetOpenMesh functions to the client

  • I don't like explicitly calling the ExecuteWrapper function.

  • I hardcoded the revision number in StoredData because the function to retrieve was coded poorly and prevented me from testing other things. I will need to go back and return this to normal later.

  • Synchronize the split window bar and the information pane bars.
  • Generate documentation using Sphinx. Preferably find a way to link documentation generation with committing to SVN.
  • Research the process of adding a SVN script that runs on commit that reports things in code such as import pdb; pdb.set_trace(). Code like this should almost always not be committed. Additionally, this script code also ensure that code is completely documented and issue a warning if it is not.

  • Output written to the shell should append to the end of the buffer rather than being inserted at the location of the cursor.
  • Logging output should go to the shell when Continuity is run from a script.
  • The following models need to be removed from the database because they depend on Numeric:
    • 9, Mesh Tutorial #1
      29, Electrophysiology Tutorial #1
      30, Electrophysiology Tutorial #2
      27, Fitting Tutorial #4

  • The following models need to be removed from the database because they depend on Tkinter:
    • 24, Fitting Tutorial #2
      25, Fitting Tutorial #3
      28, Fitting Tutorial #6

  • Functions that fetch solutions from the database should update the status bar to indicate to the user that the database is being queried because the process takes some time.
  • In StoredData, mat and active seem to have been replaced by matCoordEquations or matEquations and activeTensionEquations. mat and active should be removed if this is true.

Notes:

  • Commands must have unique names; otherwise newer commands overwrite old commands. The AddCommand function should probably be extended to include a namespace concept, perhaps.

  • The wx.FileDialog gives paths in the expected format for the platform. For example, on Windows, the separators are backslashes. On Linux, the separators are forward slashes. GetPath returns the path, including the file. GetDirectory returns the path, not including the file. GetFilename returns just the file.

  • If you make a change to the code, you can see the results of the change without restarting continuity by dynamically reloading the module. For example, to reload the commands_file module, you would type import imp, sys; imp.reload(sys.modules["client.commands_file"]) into the console. The names of all modules can be found with for key in sys.modules.keys(): print key. Note that this is not always sufficient. For example, while reloading commands_file is sufficient if you made a spelling error or a simple mistake, it will not be sufficient if you added a new menu, because the code that adds the menus is not in that module.

  • The way the menus are built has some flaws. For example, if you have two menu items with the same name, such as "model", it will not display correctly.
  • The EVT_TREE_SEL_CHANGING and EVT_TREE_SEL_CHANGED events each fire twice in Windows 7 when an item is selected. The first time the events fire the item returned by event.GetItem() is invalid. This behaviour is platform specific. An excerpt from a relevant thread that explains this behaviour:

  • Interestingly, removing the wx.TR_EXTENDED style flag from a tree control does not affect behaviour in Windows 7.

  • wx.TreeCtrl.GetSelections() returns a list of items in the order in which they appear in the tree, not the order that the items were selected.

  • There are two implementations of Advanced User Interface (aui). One, wx.aui, is simply a wrapper around the C++ aui library. The other, wx.lib.agw.aui, is a reimplementation of the C++ aui library in pure Python. I elected to use wx.lib.agw.aui.
  • An interesting article on mix-ins, in two parts:
  • Here are some notes I made while trying to understand a few things about Continuity. They are extremely rough but might be useful for someone else. They'll probably be the basis for the documentation I intend to write after finishing the coding.
    • continuity start-up: first runs the bat file
      • - bat file checks that environment variables are set - runs continuityclient.py
      continuityclient.py:
      • - handles version of python - handles general command line arguments, such as --help - calls main
        • - main creates an instance of the client and runs its mainloop
      continuityclient.py (the actual client):
      • - init is called first
        • - init sets many variables

          - then calls parent constructor (the constructor must be called after the parent constructor because the parent constructor calls OnInit but we want this to happen after the variables have been set because they are used in OnInit

        - OnInit

        • - creates the splash frame if the command line arg is set - posts an event to be done later
        - the mainloop begins

        - the first event the mainloop processes is the event that onInit posted (a call to _InitializeContinuityClient)

        • - this function actually initializes everything - sends information about its progress to the splash frame if it exists - destroys the splash frame at the end of the process and shows the windows
      initialization complete!
  • ContinuityLib.ContinuityFramework:

    • Command:
      • __init__

        • - sets the global vf reference - sets the function that is stored
      • doitWrapper
        • - logs the command if logging is set and then executes the command; if logging is not set simply executes the command
      CommandGUI:
      • __init__

        • - does nothing
        addMenuCommand
        • - sets a variable called menuInfo with menu root, name, item name, and cascade name

      CommandWrapper:

      • __init__

        • - sets cmd and renderer

        __call__

        • - renderer stops animations - if cmd has arguments, calls cmd with arguments; otherwise, calls cmd without arguments - renderer starts animations
      gui:
      • __init__

        • - sets ROOT: top-level frame - sets vf: viewer framework - sets VIEWER: renderer - sets pyshell: the console

      ContinuityFramework (also called guiFramework):

      • __init__

        • - creates an instance of gui, using the master passed in as an argument and itself as the vf - sets cleanUp function
        cleanUp
        • - stops animations - shuts down renderer - destroys console - destroys viper - destroys log - if a calibrationDialog is present, destroys calibration dialog
        createLog createShell createViperGui showLog showShell showOM (Open Mesh) askFileSave addCommand
        • - adds a command to a dictionary of commands
        loadModule
        • - imports all the *commands files

          - builds menus for them, adding handlers (which are CommandWrapper(cmd.guiCallback, renderer))

        changeFont
        • - unimplemented in old 7
        reset
        • - unimplemented in old 7
        source
        • - unimplemented in old 7
      • gui_main: Continuity:
        • __init__

          • - continuity constructor sets a bunch of variables - then does the splash form if the variable is set
            • - first creates the form - then runs a daemon
            - then calls initializeViewerFramework - if full was in command line arguments:
            • - tries to import a file - if file successfully imported, stay full; otherwise make it client only
            - if standalone in command line arguments:
            • - sets title to include standalone - if both full and standalone, standalone takes precedence - if full but not standalone, import and create the server, setting to self.server (line 202, 203)
            - used to load all modules (this is now done in initializeViewerFramework) - checks crash report - executes default script
          initializeViewerFramework
          • - creates local references - actually initializes the parent constructor - loads modules - sets renderer - shows top-level frame
          sanityCheck standAloneParse
          • - command parsing for stand-alone mode (can check to see if this is called anywhere)
          checkCrashReport writeLog runScript
        data commands:
        • loadNodesTable mergeMeshes
          • find_centroid
          find_centroids compressFittingData migrateMaterials migrateStimulus migrateOldData

          SelectSimplexBasisFunction

        gui commands:
        • reload
          • removeExtraVFWidgets
          restoreWindowPosition listWindows
          • - lists windows
          cleanUpWindows
          • - cleans up subset of windows:
            • - main window
            - anything with form, anything with strains, any open mesh controls, and any stimulus
          changeTitle resetClient resetWindows resetServer resetOpenMesh doTransButton makeImagePickles addContinuityButtons
          • - long complex function that builds the toolbar
          askFileOpen
          • - overloads the parent version - calls the parent version; the thing it does differently is add the current script to the path so that it can
            • find all the files it needs
          mainloop
          • - if has gui, begins the wx mainloop
        Command Commands:
        • doCommand doUserCommand
        Database Commands:
        • closeCommunications createDBconnection
        Rendering Related Commands:
        • floatCamera_cb setLineWidth setCameraGeometry addTransformationControls toggleUserRotation doRotation setTransformationMatrices transformViewer animateFrames
        Presumably Rendering Related Commands:
        • renumberMesh autoUpdateDimensions calc_mesh
        Server Related Commands:
        • start_server connect get
          • - sends a get command - should test to see what this does
          send_cmd send_all
  • Commands:
    • so Load, Reset, etc are classes that inherit from Command they get an init that gives them a reference to the viewer framework and the function stored in their init they have a wrapper that optionally logs the command for every command we create an instance of CommandGUI - this represents the command in the menu; all the CommandGUI is is an object with a menuInfo member that is a list that contains the menuRoot, the menuName, the itemName, and the cascadeName, whatever that is

      in loadModule, where the commands are actually used, CommandWrapper is used CommandWrapper wraps the guicallback and the renderer when the commandwrapper is called it stops animations, runs the command, then restarts animations addMenuCommand from vf seems to have supported addSeparatorBelow, but that's now gone; could be added again easily enough

Additions and Changes:

  • The code has been migrated to Python 2.6. The dependency that prevents us from using more recent versions of Python is PyGreSQL. The dependency on MGLTools has been removed.
  • The code has been migrated to Python 2.7. The steps to do this:
    • download and install MinGW

      download PyGreSQL source (this is available from the Python Package Index (http://pypi.python.org/pypi/PyGreSQL/) but not the official homepage) echo PATH=%PATH%;C:\MinGW\bin setup.py build --compiler=mingw32 setup.py install copy pg.py into pcty/client/database/ (though we should probably use the version in site-packages rather than a local version) edit continuity/global_.py and change the SUPPORTED_PYTHON_VARIABLES to ((2, 7,),) delete all pyc files

  • StoredData is now iterable. Each iteration yields a two-tuple, the next key-value pair in storedDataDict. Additionally, ContainerObj now supports a GetGroup function.

    • These changes were made to lessen the amount of hardcoding and to allow for more elegant code in the GUI. The currently used idiom is:
         1    if item in (u"equ", u"sol", u"mat", u"init", u"active", u"circModel", u"activeTensionEquations", u"matEquations"):
      

      This example, adapted from StoredData.py, selects all biomechanics data. If a new type of data is added, every occurrence of this code must be modified to accommodate it. However, if the group can be queried, then this idiom can be used:

         1    if item.obj.GetGroup() in (u"Biomechanics"):
      

      This code does not need to be changed if new types of data are added. StoredData.py and possibly the database should be modified to use GetGroup.

Installation:

Sphinx Documentation:

Known Bugs:

  • The PyCrust shell has no way of breaking out of infinite loops. This is an upstream problem.

  • Logging fails when the os module is not imported. This is an upstream problem and should be reported if it can be reproduced.

Potential Bugs:

  • In sympy_to_c.py, hundreds of symbols are created, seemingly for no good reason.

  • The fitting code apparently creates millions of triangles, too, regardless of how many will be needed - Adarsh told me this.

Conventions:

  • In general, I follow the Python style guidelines outlined in PEP 8. However, there are a few places where I deviate. I use tabs instead of spaces. The question of tabs versus spaces is a programmer holy war. Any decent IDE will allow you to switch to spaces if tabs sadden you. Also, naming conventions for everything except modules differ from the Python guidelines. In order to be consistent with wxPython code, which uses C++ conventions, I have adopted C++ conventions everywhere throughout my code.
  • In my code and comments, I refer to a cont6 file as a "solution" and individual models (such as the constitutive model and the ionic model) as "models" to disambiguate them. Model is overloaded, however, because it also refers to model as in Model-View-Presenter.

Scripts:

find.py:
This script simply searches Continuity's source in search of a specific string. To set up the script, change the value of the variable pcty_path top the path to your working copy. To use the script, type the string that you wish to search for and press Enter.

   1 #!/usr/bin/python
   2 # vim: set fileencoding=utf-8 :
   3 # rjt - rjturner@ucsd.edu
   4 
   5 from __future__ import with_statement
   6 
   7 import os
   8 
   9 pcty_path = r"C:\Users\rjt\Desktop\Continuity7.0\pcty"
  10 
  11 string_to_find = raw_input()
  12 
  13 is_finished = False
  14 results = {}
  15 while not is_finished:
  16     for root_directory, directories, files in os.walk(pcty_path):
  17         if ".svn" in directories:
  18             directories.remove(r".svn")
  19         for file_ in files:
  20             if ".cont6" in file_:
  21                 files.remove(file_)
  22             elif ".pyc" in file_:
  23                 files.remove(file_)
  24             elif ".pyd" in file_:
  25                 files.remove(file_)
  26         for file_ in files:
  27             file_path = os.path.join(root_directory, file_)
  28             with open(file_path) as current_file:
  29                 for line_number, line in enumerate(current_file):
  30                     if string_to_find in line:
  31                         result = (line_number + 1, line.strip())
  32                         if file_path not in results:
  33                             results[file_path] = [result]
  34                         else:
  35                             results[file_path].append(result)
  36 
  37     print "".join([r"The string ", string_to_find, r" was found in:"])
  38     print ""
  39 
  40     for each_file in results:
  41         print each_file
  42     print ""
  43 
  44     for each_file, matches in results.items():
  45         print "".join([each_file, ":"])
  46         for each_match in matches:
  47             print "".join(["%04d:" % (each_match[0]), each_match[1]])
  48         print ""
  49 
  50     string_to_find = raw_input()
  51 
  52     if string_to_find == "":
  53         is_finished = True

Mappings:

  • doSplash => withSplashFrame

  • stored_data => model

  • withShell => withConsole

  • allCommands => commands

  • gui => menu

  • cmd => instance

  • initModule => InitializeModule

  • addCommand => AddCommand

  • loadModule => LoadModule

  • took out log keyword loadModule
  • biomechanicsCommands => commands_biomechanics

  • fileCommands => commands_file

  • editCommands => commands_edit

  • fittingCommands => commands_fitting

Obsolete?

  • threads - I remember seeing this set to false by default, after it read in what the user asked for, so it would effectively always be false - is this no longer in use?
  • package - documentation states that it is for finding menus in the viewer framework, I have a new menu system, so this is likely obsolete

MenuBar code:

   1                 Menu = MenuUtilities.MenuDataStructure
   2                 MenuItem = MenuUtilities.MenuItemDataStructure
   3                 MenuSeparator = MenuUtilities.MenuSeparatorDataStructure
   4                 menuBarDataStructure = [
   5                                 Menu(text=u"&File", id_=wx.ID_FILE, menuItems=[
   6                                                 MenuItem(text=u"&New",         helpString=u"Open a new solution.", id_=wx.ID_NEW),
   7                                                 MenuItem(text=u"&Open...",     helpString=u"Open an existing solution.", id_=wx.ID_OPEN),
   8                                                 MenuItem(text=u"&Save",        helpString=u"Save the current solution under the current name.", id_=wx.ID_SAVE),
   9                                                 MenuItem(text=u"&Save As...",  helpString=u"Save the current solution under a specified name.", id_=wx.ID_SAVEAS),
  10                                                 MenuItem(text=u"&Exit",        helpString=u"Terminate Continuity.", handler=self.OnExit, accelerator=u"CTRL+X", id_=wx.ID_EXIT),
  11                                                 MenuSeparator(),
  12                                                 # XXX: Recent Files requires a help string and almost certainly has a stock ID. 
  13                                                 MenuItem(text=u"Recent Files"),
  14                                 ]),
  15                                 Menu(text=u"&Edit", id_=wx.ID_EDIT, menuItems=[
  16                                                 MenuItem(text=u"&Properties...", helpString=u"Edit Continuity properties.", id_=wx.ID_PROPERTIES),
  17                                 ]),
  18                                 Menu(text=u"&View", menuItems=[
  19 
  20                                 ]),
  21                                 Menu(text=u"Mesh", menuItems=[
  22                                                 Menu(text=u"&Edit", id_=wx.ID_EDIT, menuItems=[
  23                                                                 MenuItem(text=u"Coordinates...", helpString=u""),
  24                                                                 MenuItem(text=u"Material Coordinates...", helpString=u""),
  25                                                                 MenuItem(text=u"Basis...", helpString=u""),
  26                                                 ]),
  27                                                 MenuItem(text=u"Refine...", helpString=u""),
  28                                 ]),
  29                                 Menu(text=u"Fitting", menuItems=[
  30                                                 MenuItem(text=u"Edit...", helpString=u"Edit fitting data."),
  31                                                 MenuItem(text=u"Fit Data", helpString=u"Fit data."),
  32                                 ]),
  33                                 Menu(text=u"Electrophysiology", menuItems=[
  34                                                 Menu(text=u"&Edit", id_=wx.ID_EDIT, menuItems=[
  35                                                                 MenuItem(text=u"Ionic Model...", helpString=u""),
  36                                                                 MenuItem(text=u"Constraints...", helpString=u""),
  37                                                 ]),
  38                                                 Menu(text=u"Calculate", id_=wx.ID_ANY, menuItems=[
  39                                                                 MenuItem(text=u"Constraints", helpString=u""),
  40                                                 ]),
  41                                                 Menu(text=u"Render", id_=wx.ID_ANY, menuItems=[
  42                                                                 MenuItem(text=u"Solution", helpString=u""),
  43                                                 ]),
  44                                 ]),
  45                                 Menu(text=u"Biomechanics", menuItems=[
  46                                                 Menu(text=u"&Edit", id_=wx.ID_EDIT, menuItems=[
  47                                                                 MenuItem(text=u"Constitutive Model...", helpString=u""),
  48                                                                 MenuItem(text=u"Boundary Conditions...", helpString=u""),
  49                                                                 MenuItem(text=u"Dynamic Model...", helpString=u""),
  50                                                                 MenuItem(text=u"Circulation Model...", helpString=u""),
  51                                                 ]),
  52                                                 Menu(text=u"Li&st", id_=wx.ID_EDIT, menuItems=[
  53                                                                 MenuItem(text=u"Stress And Strain...", helpString=u""),
  54                                                 ]),
  55                                                 Menu(text=u"&Render", id_=wx.ID_EDIT, menuItems=[
  56                                                                 MenuItem(text=u"Surface...", helpString=u""),
  57                                                 ]),
  58                                                 MenuItem(text=u"Solve Nonlinear...", helpString=u""),
  59                                 ]),
  60                                 Menu(text=u"Window", menuItems=[
  61                                                 MenuItem(text=u"Show Solution Information Pane",          helpString=u"", kind=wx.ITEM_CHECK, id_=wx.ID_ANY),
  62                                                 MenuItem(text=u"Show Solution Database Information Pane", helpString=u"", kind=wx.ITEM_CHECK, id_=wx.ID_ANY),
  63                                                 MenuItem(text=u"Show Interactive Console Pane",           helpString=u"", kind=wx.ITEM_CHECK, id_=wx.ID_ANY),
  64                                 ]),
  65                                 Menu(text=u"Help", menuItems=[
  66                                                 MenuItem(text=u"&About", helpString=u"Display information about the program.", id_=wx.ID_ABOUT),
  67                                 ]),
  68                 ]
  69                 menuBar = MenuUtilities.CreateMenuBar(menuBarDataStructure, self)
  70                 self.SetMenuBar(menuBar)
  71                 return menuBar

   1 #!/usr/bin/python -tt
   2 # vim : set fileencoding=utf-8 :
   3 # rjt - rjturner@ucsd.edu
   4 
   5 """
   6 """
   7 
   8 import wx
   9 
  10 import wx.lib.scrolledpanel
  11 
  12 class ServersList(wx.Panel):
  13         def __init__(self, parent):
  14                 wx.Panel.__init__(self, parent)
  15 
  16                 sizer = wx.BoxSizer(wx.VERTICAL)
  17 
  18                 title = wx.StaticText(parent=self, label=u"Servers")
  19                 sizer.Add(
  20                                 item=title,
  21                                 proportion=0,
  22                                 flag=wx.ALIGN_LEFT | wx.ALL,
  23                                 border=5
  24                                 )
  25 
  26                 staticLine = wx.StaticLine(self)
  27                 sizer.Add(
  28                                 item=staticLine,
  29                                 proportion=0,
  30                                 flag=wx.ALIGN_CENTER | wx.ALL | wx.EXPAND,
  31                                 border=5
  32                                 )
  33 
  34                 panels = ScrolledPanels(self)
  35                 sizer.Add(
  36                                 item=panels,
  37                                 proportion=1,
  38                                 flag=wx.ALIGN_CENTER | wx.ALL | wx.EXPAND,
  39                                 border=5
  40                                 )
  41 
  42                 button = wx.Button(self)
  43                 sizer.Add(button)
  44                 button.Bind(wx.EVT_BUTTON, self.OnTest)
  45 
  46                 self.SetSizer(sizer)
  47                 sizer.SetVirtualSizeHints(self)
  48 
  49                 self.panels = panels
  50                 self.sizer = sizer
  51                 self.staticLine = staticLine
  52                 self.title = title
  53 
  54 
  55         def AppendPanel(self, *args, **kwargs):
  56                 self.panels.AppendPanel()
  57 
  58 
  59         def OnTest(self, event):
  60                 self.AppendPanel()
  61 
  62 
  63 #---------------
  64 
  65 class ScrolledPanels(wx.lib.scrolledpanel.ScrolledPanel):
  66         def __init__(self, parent):
  67                 print "__init__"
  68                 wx.lib.scrolledpanel.ScrolledPanel.__init__(self, parent)
  69                 self.numberOfPanels = 0
  70                 self.panels = []
  71                 self.SetupScrolling(
  72                                 scroll_x=False,
  73                                 scroll_y=True,
  74                                 rate_x=0,
  75                                 rate_y=0,
  76                                 )
  77                 self.sizer = wx.BoxSizer(wx.VERTICAL)
  78                 self.SetSizer(self.sizer)
  79                 self.sizer.Fit(self)
  80         def AppendPanel(self, *args, **kwargs):
  81                 print "Add"
  82                 numberOfPanels = self.numberOfPanels
  83                 numberOfPanels = numberOfPanels + 1
  84                 scrollItem = ScrollItem(self, "Local Host", "4455", ["DejaVu", "Viper"])
  85                 width, height = scrollItem.GetSizeTuple()
  86                 self.SetupScrolling(
  87                                 scroll_x=False,
  88                                 scroll_y=True,
  89                                 rate_x=0,
  90                                 rate_y=height+4,
  91                                 )
  92                 self.sizer.Add(
  93                                 item=scrollItem,
  94                                 proportion=0,
  95                                 flag=wx.ALL | wx.EXPAND,
  96                                 border=2
  97                                 )
  98                 self.sizer.SetVirtualSizeHints(self)
  99                 self.Refresh()
 100                 self.panels.append(scrollItem)
 101 
 102 
 103 # class ScrolledPanels(wx.lib.scrolledpanel.ScrolledPanel)
 104 #------------------------------------------------------------------------------
 105 
 106 class ScrollItem(wx.Panel):
 107         """
 108         """
 109         def __init__(self, parent, serverName, serverPort, defaultRenderer):
 110                 """
 111                 """
 112                 wx.Panel.__init__(self, parent)
 113 
 114                 sizer = wx.BoxSizer(wx.VERTICAL)
 115 
 116                 serverName = wx.StaticText(parent=self, label=serverName + u":" + serverPort)
 117 
 118                 statusSizer = wx.BoxSizer(wx.HORIZONTAL)
 119                 statusIcon = wx.StaticText(self, wx.ID_ANY, "|=|")
 120                 status = wx.StaticText(self, wx.ID_ANY, u"Idle")
 121 
 122                 statusSizer.Add(statusIcon, 0, wx.ALIGN_LEFT | wx.ALL)
 123                 statusSizer.Add(status, 0, wx.ALIGN_LEFT | wx.ALL)
 124 
 125                 rendererChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, [100,-1],
 126                         defaultRenderer, 0)
 127 
 128                 sizer.Add(serverName, 0, wx.ALIGN_LEFT | wx.ALL, 2)
 129                 sizer.Add(statusSizer, 0, wx.ALIGN_LEFT | wx.ALL, 2)
 130                 sizer.Add(rendererChoice, 0, wx.ALIGN_LEFT | wx.ALL, 2)
 131 
 132                 self.SetSizer(sizer)
 133                 sizer.Fit(self)
 134 
 135                 self.sizer = sizer
 136 
 137                 #self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseClick)
 138 
 139 
 140         def OnMouseClick(self, event):
 141                 """
 142                 """
 143                 self.SetBackgroundColour(u"BLUE")
 144 
 145 
 146 # class ScrollItem(wx.Panel)
 147 #------------------------------------------------------------------------------
 148 
 149 
 150 if __name__ == u"__main__":
 151         class Application(wx.App):
 152                 def OnInit(self):
 153                         frame = wx.Frame(None)
 154                         sizer = wx.BoxSizer(wx.VERTICAL)
 155                         scrolledView = ServersList(frame)
 156                         sizer.Add(
 157                                         item=scrolledView,
 158                                         proportion=1,
 159                                         flag=wx.ALL | wx.EXPAND,
 160                                         border=5
 161                                         )
 162                         frame.SetSizer(sizer)
 163                         frame.SetSize(wx.Size(300, 500))
 164                         frame.Show()
 165                         self.SetTopWindow(frame)
 166 
 167                         self.frame = frame
 168                         self.sizer = sizer
 169                         self.scrolledView = scrolledView
 170 
 171                         return True
 172 
 173         application = Application(redirect=False)
 174         application.MainLoop()
 175 
 176 import wx
 177 
 178 class FiltersList(wx.Panel):
 179         def __init__(self, parent):
 180                 wx.Panel.__init__(self, parent)
 181 
 182                 sizer = wx.BoxSizer(wx.VERTICAL)
 183 
 184                 title = wx.StaticText(parent=self, label=u"Filters")
 185                 sizer.Add(title, 0, wx.ALIGN_LEFT | wx.ALL, 5)
 186 
 187                 staticLine = wx.StaticLine(self)
 188                 sizer.Add(staticLine, 0, wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, 5)
 189 
 190                 style = (
 191                                 wx.TR_EXTENDED      |
 192                                 wx.TR_HAS_BUTTONS   |
 193                                 wx.TR_HIDE_ROOT     |
 194                                 wx.TR_LINES_AT_ROOT |
 195                                 wx.TR_MULTIPLE      |
 196                                 wx.SUNKEN_BORDER
 197                                 )
 198                 filterDisplay = wx.TreeCtrl(
 199                                 parent=self,
 200                                 style=style
 201                                 )
 202                 filterDisplay.AddRoot(u"virtual")
 203                 byRepository = filterDisplay.AppendItem(filterDisplay.GetRootItem(), u"By Repository:")
 204                 byType = filterDisplay.AppendItem(filterDisplay.GetRootItem(), u"By Type:")
 205                 filterDisplay.AppendItem(byRepository, u"Official Continuity Repository")
 206                 filterDisplay.AppendItem(byRepository, u"Local Repository")
 207                 filterDisplay.AppendItem(byType, u"Biomechanics")
 208                 filterDisplay.AppendItem(byType, u"Electrophysiology")
 209                 filterDisplay.AppendItem(byType, u"Mesh")
 210                 filterDisplay.ExpandAll()
 211 
 212                 sizer.Add(filterDisplay, 1, wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, 5)
 213 
 214                 searchSizer = wx.BoxSizer(wx.HORIZONTAL)
 215 
 216                 filterButton = wx.Button(parent=self, label=u"Filter")
 217                 searchSizer.Add(filterButton, 0, wx.ALIGN_LEFT | wx.ALL, 5)
 218 
 219                 filterString = wx.ComboBox(
 220                                 parent=self,
 221                                 choices=[u"Clear History"],
 222                                 style=wx.CB_DROPDOWN | wx.TE_PROCESS_ENTER
 223                                 )
 224                 searchSizer.Add(filterString, 1, wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 5)
 225 
 226                 sizer.Add(searchSizer, 0, wx.ALIGN_CENTER | wx.ALL | wx.EXPAND, 5)
 227 
 228                 self.SetSizer(sizer)
 229                 sizer.SetSizeHints(self)
 230 
 231                 filterDisplay.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnFilterSelected)
 232                 filterButton.Bind(wx.EVT_BUTTON, self.OnFilterButton)
 233                 filterString.Bind(wx.EVT_TEXT_ENTER, self.OnFilterButton)
 234                 filterString.Bind(wx.EVT_COMBOBOX, self.OnFilterButton)
 235 
 236                 self.filterButton = filterButton
 237                 self.filterDisplay = filterDisplay
 238                 self.filterString = filterString
 239                 self.searchSizer = searchSizer
 240                 self.sizer = sizer
 241                 self.staticLine = staticLine
 242                 self.title = title
 243 
 244 
 245         def Filter(self, filter_):
 246                 print u"filter_ =", filter_
 247 
 248 
 249         def OnComboBoxSelection(self, event):
 250                 if filter_ == u"Clear History":
 251                         filterString.Clear()
 252                         filterString.Append(u"Clear History")
 253 
 254         def OnFilterButton(self, event):
 255                 filterString = self.filterString
 256                 filter_ = filterString.GetValue()
 257                 if filter_ == u"Clear History":
 258                         filterString.Clear()
 259                         filterString.Append(u"Clear History")
 260                 else:
 261                         filterString.Insert(filter_, 0)
 262                         self.Filter(filter_)
 263                 filterString.SetValue(u"")
 264 
 265 
 266         def OnFilterSelected(self, event):
 267                 import pdb; pdb.set_trace()
 268 
 269 
 270 # class ListFilters(wx.Panel)
 271 #------------------------------------------------------------------------------
 272 
 273 if __name__ == u"__main__":
 274         class Application(wx.App):
 275                 def OnInit(self):
 276                         frame = wx.Frame(None)
 277                         sizer = wx.BoxSizer(wx.VERTICAL)
 278                         filtersList = FiltersList(frame)
 279                         sizer.Add(
 280                                         item=filtersList,
 281                                         proportion=1,
 282                                         flag=wx.ALL | wx.EXPAND,
 283                                         border=5
 284                                         )
 285                         frame.SetSizer(sizer)
 286                         frame.SetSize(wx.Size(300, 500))
 287                         frame.Show()
 288                         self.SetTopWindow(frame)
 289 
 290                         self.frame = frame
 291                         self.sizer = sizer
 292                         self.filtersList = filtersList
 293 
 294                         return True
 295 
 296         application = Application(redirect=False)
 297         application.MainLoop()


CategoryHomepage